8

使用 react-router-redux,似乎获取路由信息的唯一方法是仅通过 props。这是正确的吗?

这大致是我现在在我的应用程序中所做的事情:

<Provider store={Store}>
  <Router history={history}>
    <Route path="/" component={App}>
      <Route path="child/:id" />
    </Route>
  </Router>
</Provider>

应用程序

const App = (props) => 
  <div className="app">
    <Header />
    <Main {...props}/>
    <Footer />
  </div>

主要的

const Main = (props) => 
  <div>
    <MessageList {...props}/>
  </div>

消息列表

let MessageList = (props) => {
  const {id} = props;

  // now I can use the id from the route
 }

const mapStateToProps = (state, props) => {
  return {
    id: props.params.id
  };
};

MessageList = connect(mapStateToProps)(MessageList)

想做的是从我的所有组件中删除 {...props} ,并将 MessageList 变成这样:

let MessageList = (props) => {
  const {id} = props;

  // now I can use the id from the route
 }

const mapStateToProps = (state) => {
  return {
    id: state.router.params.id
  };
};

MessageList = connect(mapStateToProps)(MessageList)

对于 Redux 让我的应用程序变得多么干净,必须在所有东西中传递 props 感觉就像是一个很大的倒退。所以如果传递参数是正确的,我想知道为什么那更可取?

我提出这个问题的具体案例:

我有一个发送消息的 UserInput 组件(发送 SEND_MESSAGE 操作)。根据当前页面(聊天室、消息提要、单个消息等),reducer 应将其放在正确的位置。但是,使用 react-redux-router,reducer 不知道路由,所以它不知道将消息发送到哪里。

为了解决这个问题,我需要传递道具,将 id 附加到我的 SEND_MESSAGE 操作中,现在原本简单的 UserInput 正在处理我的应用程序的业务逻辑。

4

1 回答 1

9

我不会解决您的问题(如何读取状态),而是自己解决您的问题(如何根据当前路线调度不同的操作)。

让你UserInput的一个展示组件。let 不是在其中进行调度,而是接受onSend由所有者组件提供的回调的 prop。输入会this.props.onSend(text)在不了解 Redux 或路由的情况下调用。

然后,还制作一个接受作为道具MessageList的展示组件,并将其转发到. 同样,将不知道路线,并将其传递给.onSendMessageUserInputMessageList<UserInput onSend={this.props.onSendMessage} />

最后,创建几个包装不同用例的容器组件:MessageList

聊天室消息列表

const mapDispatchToProps = (dispatch) => ({
  onSendMessage(text) {
    dispatch({ type: 'SEND_MESSAGE', where: 'CHAT_ROOM', text })
  }
})

const ChatRoomMessageList = connect(
  mapStateToProps,
  mapDispatchToProps
)(MessageList)

提要消息列表

const mapDispatchToProps = (dispatch) => ({
  onSendMessage(text) {
    dispatch({ type: 'SEND_MESSAGE', where: 'FEED', text })
  }
})

const FeedMessageList = connect(
  mapStateToProps,
  mapDispatchToProps
)(MessageList)

现在您可以直接在路由处理程序中使用这些容器组件。他们将指定正在调度哪个动作,而不会将这些细节泄露给下面的演示组件。让您的路由处理程序负责读取 ID 和其他路由数据,但尽量避免将这些实现细节泄露给下面的组件。在大多数情况下,当它们由道具驱动时会更容易。


解决最初的问题,不,如果您使用react-router-redux. 从自述文件

您不应该直接从 Redux 存储中读取位置状态。这是因为 React Router 是异步操作的(用于处理诸如动态加载的组件之类的事情),并且您的组件树可能尚未与您的 Redux 状态同步更新。你应该依赖 React Router 传递的 props,因为它们只有在处理完所有异步代码后才会更新。

有一些实验项目确实在 Redux保留了整个路由状态,但它们也有其他缺点(例如,React 路由器状态是不可序列化的,这与 Redux 的工作方式相反)。所以我认为我上面写的建议应该可以很好地解决你的用例。

于 2016-02-27T19:55:40.297 回答