使用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处理我的应用程序的业务逻辑。
答案 0 :(得分:9)
我将解决您的问题(如何根据当前路线调度不同的操作),而不是解决您的问题(如何阅读状态)。
让UserInput
成为presentational component。不要在其中调度,而是接受onSend
prop,它是所有者组件提供的回调。输入将在不知道任何有关Redux或路由的情况下调用this.props.onSend(text)
。
然后,将MessageList
也设为接受onSendMessage
作为道具的演示组件,并将其转发给UserInput
。同样,MessageList
将不知道路线,并将其传递给<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状态读取路由器参数。来自README:
您不应直接从Redux商店读取位置状态。这是因为React Router异步操作(处理诸如动态加载的组件之类的东西),并且组件树可能尚未与Redux状态同步更新。你应该依赖React Router传递的道具,因为它们只有在处理完所有异步代码后才会更新。
有一些experimental projects 做在Redux中保留整个路由状态,但它们还有其他缺点(例如,React Router状态是不可序列化的,这与Redux的工作方式相反)。所以我认为我上面写的建议应该可以很好地解决你的用例。