在路由更改时更新 Redux 状态
Posted
技术标签:
【中文标题】在路由更改时更新 Redux 状态【英文标题】:Update Redux state on route change 【发布时间】:2016-10-21 00:48:10 【问题描述】:我一直试图弄清楚这一点,但我越来越困惑。
我想在每次离开或更改路线时重置/更改 Redux 状态。我使用 react-router-redux
和 history.listener
在每次路由更改时调度一个动作
history.listen(location => store.dispatch(resetManualsCategory()));
动作创建者:
export function resetManualsCategory()
return
type: 'RESET_MANUALS_CATEGORY'
减速器
export function manualCategories(state=[], action)
switch (action.type)
case 'SELECT_MANUALS_CATEGORY':
[...]
case 'RESET_MANUALS_CATEGORY':
console.log('test reducer');
return Object.assign(, state,
manualCategory: 'test'
)
default:
return state
最让我困惑的是,如果我刷新页面或在顶部导航中单击两次路由,状态会更新,但是即使动作和减速器触发,单个路由更改也不会影响 redux 状态(显示控制台中的测试消息)。
我做错了什么,这里到底发生了什么?
【问题讨论】:
【参考方案1】:我在更改路线时使用了不同的方法来重置状态。我没有收听历史/路由器,而是在我的页面容器上使用componentWillMount
事件来调度“重置页面”操作。
示例:
路由器:
<Provider store=store>
<Router history=history>
<Route path="/page1" component=Page1Container />
<Route path="/page2" component=Page2Container />
</Router>
</Provider>
Page1 容器:
class Page1Container extends Component
componentWillMount()
this.props.resetPage()
render()
// render Page1
const mapStateToProps = (state) =>
return
// ...
const mapDispatchToProps = (dispatch) =>
return
// ...
resetPage: () => dispatch(type: 'PAGE1_RESET_PAGE')
export default connect(mapStateToProps, mapDispatchToProps)(Page1Container)
减速机:
const initialState = null
export function Page1Reducer (state = initialState, action)
switch (action.type)
case 'PAGE1_RESET_PAGE':
state = initialState
break
// ...
更新: 正如@DavidHarkness 提到的,这种方法的缺陷是组件在安装时会渲染两次。 除此之外,我现在倾向于认为这种解决方案并不优雅,最好避免在组件内部使用业务逻辑。 在 reducer 中移动逻辑将是一个更好的选择(请参阅@DiegoHaz 答案)。
【讨论】:
如果由于某种原因您只需要重置组件使用的状态部分,这似乎是一个很好的解决方案。 这不是用之前的状态渲染,然后立即用新的状态再次渲染吗?【参考方案2】:目前我正在使用componentWillUnmount() 来执行此操作。我在减速器中有一个动作设置,我想重置以重置其状态,并从 componentWillUnmount() 方法调度该动作。
您可能会遇到的一个问题是,当使用 React Router 时,路由更改不会触发刷新,并且组件不会重新安装在同一路由上,例如,如果您有一个 posts/new 和一个 posts/edit /:id 路由都使用同一个组件来编辑帖子,在这些路由之间切换不会导致组件重新挂载。
因为这个 componentWillUnmount() 将 NOT 运行,相同的组件只会接收新的道具。因此,您可以使用 componentWillReceiveProps(newProps) 进行比较并进行相应的更新。
如果您确实想强制重新挂载组件,您需要确保要重新挂载的组件具有不同的键属性,请参阅here 和here 了解更多信息。
【讨论】:
【参考方案3】:react-router-redux
提供了一个 LOCATION_CHANGE
动作,该动作已经在每次路由更改时调度。你可以做的很简单:
import LOCATION_CHANGE from 'react-router-redux'
export function manualCategories(state=[], action)
switch (action.type)
case LOCATION_CHANGE:
/*
action.payload is something like:
pathname: '/',
search: '',
hash: '',
state: null,
action: 'PUSH',
key: 'xwl8yl',
query: ,
$searchBase:
search: '',
searchBase: ''
*/
default:
return state
【讨论】:
是LOCATION_CHANGE
和@@router/LOCATION_CHANGE
一样吗?
是的。您也可以使用“@@router/LOCATION_CHANGE”,但不建议这样做。
我刚刚意识到是什么导致了这个问题,它与这个问题略有不同。也许你能帮忙? ***.com/questions/37912180/…
如果您只想重置特定路线的状态,这是否也适用?
这个答案不再起作用了。 react-router-redux 已重命名为 connected-react-router,并且看起来不再像以前那样工作了。以上是关于在路由更改时更新 Redux 状态的主要内容,如果未能解决你的问题,请参考以下文章
REACT + REDUX:在 redux 状态更改时 mapStateToProps 更新状态,但视图未按照新状态呈现
触发 Redux 操作以响应 React Router 中的路由转换