路线更改时更新Redux状态

时间:2016-06-19 19:36:01

标签: reactjs redux react-router-redux

我一直试图弄清楚这一点,我越来越困惑。

我想在每次离开或更改路线时重置/更改Redux状态。我正在使用react-router-redux history.listener每次路由更改时都会调度操作

history.listen(location => store.dispatch(resetManualsCategory()));

行动创作者:

export function resetManualsCategory() {
    return {
        type: 'RESET_MANUALS_CATEGORY'
    }
}

Reducer

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状态,即使操作和减速器触发(显示在控制台中测试消息。

我做错了什么以及这里发生了什么?

3 个答案:

答案 0 :(得分:13)

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
    }
}

答案 1 :(得分:5)

我在改变路线时使用了不同的方法来重置状态。我没有收听历史记录/路由器,而是在页面容器上使用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
    }

    // ...
  }
}

答案 2 :(得分:1)

目前我正在使用componentWillUnmount()来执行此操作。我在reducer中有一个动作设置我要重置以重置其状态,我从 componentWillUnmount()方法调度动作。

您可能遇到的一个问题是,当使用React Router时,路由更改不会触发刷新,组件也不会在同一路由上重新安装,例如,如果您有帖子/新帖子和帖子/编辑/:id路由都使用相同的组件来编辑帖子,在这些路由之间进行不会导致组件重新安装。

由于 componentWillUnmount() NOT 运行,因此相同的组件将只接收新的道具。因此,您可以使用 componentWillReceiveProps(newProps)来执行比较并相应地更新。

如果您确实要强制重新装配组件,则需要确保要重新装入的组件具有不同的键属性,有关详细信息,请参阅herehere