Sync redux store with react-router route location (update header on route change)

…衆ロ難τιáo~ 提交于 2019-12-23 02:56:05

问题


I am using react-router-redux and I'm trying to update the header of my app, that receives it's state from the store, whenever the route changes (@@router/UPDATE_LOCATION)

Currently I'm dispatching actions in a componentWillMount like:

  componentWillMount() {
    this.props.appActions.setHeader('New Block')
  }

When I manually set the header in componentWillMount on route /blocks/new, and it is a child of a route 'blocks', who both have a different header, it doesn't work when I go back in history, because the component of route blocks does not mount again, it is still mounted. Thus the header is still New Block. And not what its own header was before, when blocks mounted, and new was still unmounted as child.

(And when I try to reverse time with the redux-devtools, what seems to happen then, every time I go back to a point where a component mounts again, it will dispatch the action again, and the devtool will receive another dispatch.)

The routes:

<Route path="begin" component={PlayerBeginContainer}>
    <IndexRoute component={PlayerOverview}/>
       <Route path="blocks" component={PlayerBlocks}>
         <Route path="new" component={PlayerNewBlock}/>
       </Route>
</Route>
...

I've tried to sync the store whenever a route changes, but:

if (action && action.type === UPDATE_LOCATION) {
 let path = action.payload.pathname.split('/')
 // Laboriously iterate through array to figure out what the new header state should be.
  // i.e. if (1 in split && split[1] === 'routeName')
  // or let lastPath = path[path.length - 1]
  // and getting parentPath would require more checking of whether it is the parent itself or not etc.
  // appHeader = 'routeHeader'
  return Object.assign({}, state, { appHeader: appHeader});
}

This gets very tedious when you just need it to trigger on a specific sub-route, And I want to avoid making another nested structure, while I already have that defined in the router.

In the header I can't use anything other than this.props.location.pathname either to try and figure out which route i'm on, and the components themselves should not bother with setting the header themselves (i.e. in componentWillMount).

Last option would be to use the router onEnter, but I'd like to keep the router clean, but perhaps I need to compromise on this.

Is there something I'm missing here? Or some sort of lib that can help me with this?

TL;DR: How can I make my header component aware of which route we are on, without having to break down the location.pathname to figure out where we are?


回答1:


This is code from one of my codebases. In this app i use hash history, but i think you could do same thing with other history objects too.

import {hashHistory} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';

const history = syncHistoryWithStore(hashHistory, store);
history.listen(location => {
   // here you can do something after location is updated
});

<Router history={history}>
 ....
</Router>

and then in you components you can get some info from state.routing:

function mapStateToProps(state) {
  return {
    current: state.routing.locationBeforeTransitions.pathname,
  };
}

export default connect(mapStateToProps)(App);

To change route from some component, do this:

import {push} from 'react-router-redux';
this.props.dispatch(push('/route'));


来源:https://stackoverflow.com/questions/39972785/sync-redux-store-with-react-router-route-location-update-header-on-route-change

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!