问题
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