使用React Redux路由器,我应该如何访问路由的状态?

时间:2016-02-27 04:37:31

标签: react-router redux react-router-redux

使用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>

MessageList中

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如何清理我的应用程序的一大步。因此,如果传递参数是正确的,我想知道为什么这更好?

我提出的具体案例:

我有一个发送消息的UserInput组件(调度SEND_MESSAGE操作)。根据当前页面(聊天室,消息馈送,单个消息等),reducer应将其放在正确的位置。但是,使用react-redux-router,reducer不知道路由,因此无法知道在哪里发送消息。

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

1 个答案:

答案 0 :(得分:9)

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

UserInput成为presentational component。不要在其中调度,而是接受onSend prop,它是所有者组件提供的回调。输入将在不知道任何有关Redux或路由的情况下调用this.props.onSend(text)

然后,将MessageList也设为接受onSendMessage作为道具的演示组件,并将其转发给UserInput。同样,MessageList将不知道路线,并将其传递给<UserInput onSend={this.props.onSendMessage} />

最后,为不同的用例创建一些包含MessageList容器组件:

ChatRoomMessageList

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

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

FeedMessageList

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

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

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

解决原始问题,不,如果您使用react-router-redux,则不应尝试从Redux状态读取路由器参数。来自README

  

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

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