I don't have a proposal for an API here. Just thinking out loud – it might be nice if in addition to the current render middleware hook, we had a way to inject additional properties into nextState used on onEnter hooks.
This lets people move stuff like injecting Redux state or a Relay environment into the library level. Users can accomplish this right now by closing over those values in creating routes, but I think the API would be cleaner if there were a hook to add those values onto the nextState argument to the onEnter hook.
onEnter gets a nextState of the router as an argument, but is there a way to access the current state? It seems onEnter doesn't have access to the router object...
You probably want onChange. It doesn't make sense to pass the "current" state into onEnter because at that point we've already left the previous route and have committed to loading the next one.
To be clear, this isn't talking about _router_ state. This is talking about injecting stuff like the Redux store or the Relay environment, to make it easier to interact with those, rather than e.g. having to close over those in your route definition.
That's one of the big reasons why Router 1.x uses an onEnter hook on the route rather than a static hook on the route component – to allow closing over the store... but that doesn't work super great with things like async loaded route configs... so let's try to do better.
How about something similar to react-redux's provider, a top level component that you pass in props which will be made available to onEnter/onLeave?
@BerkeleyTrue That's kind of what I have in mind, but I reckon we wouldn't need to create a new component. Instead, we could just use the <Router> component. Any non-standard props passed to the <Router> component would then be passed into the hooks.
<Router
routes={routes}
history={browserHistory}
/* props below are arbitrary and will be passed into enter/leave/change hooks */
store={store}
dispatch={store.dispatch}
/>
const routes = (
<Route component={App} path="/">
<Route path="groups" component={Groups} />
<Route path="users" component={Users} onEnter={checkAuth} />
</Route>
);
function checkAuth({ nextState, replace, store, dispatch }, executeTransition) {
return dispatch(someAuthAction()).then(executeTransition);
}
Of course, this would be a breaking change. That said, because the behavior around enter/leave/change hooks depends on the arity of the hooks, I reckon it'd be tough to make this change without breaking changes. I suppose we could make this opt-in on a route-by-route basis and deprecate the old approach. This way, you'll only use the new hook signature if you specify a prop on the route component (e.g., <Route path="users" component={Users} onEnter={checkAuth} newHooks={true} />). We could then deprecate enter/leave/change hooks with an invalid number of arguments. I think this is a really messy approach though.
I have a pretty good idea of how I would implement this, and I think this would be a great change to the library if we can work out the finer points of the API and decide on a transition plan. Any thoughts, @taion?
Could you please explain why this issue has been closed? has it been implemented in v4? could you please provide a link? Thanks!
I think I have found the answer in v4 readme
I don't quite follow @klarezz; did that doc specify how to do this? To inject some information I get from a Store by adding it to the nextState.params object in onEnter, but this feels a bit hacky.
Most helpful comment
@BerkeleyTrue That's kind of what I have in mind, but I reckon we wouldn't need to create a new component. Instead, we could just use the
<Router>component. Any non-standard props passed to the<Router>component would then be passed into the hooks.Of course, this would be a breaking change. That said, because the behavior around enter/leave/change hooks depends on the arity of the hooks, I reckon it'd be tough to make this change without breaking changes. I suppose we could make this opt-in on a route-by-route basis and deprecate the old approach. This way, you'll only use the new hook signature if you specify a prop on the route component (e.g.,
<Route path="users" component={Users} onEnter={checkAuth} newHooks={true} />). We could then deprecate enter/leave/change hooks with an invalid number of arguments. I think this is a really messy approach though.I have a pretty good idea of how I would implement this, and I think this would be a great change to the library if we can work out the finer points of the API and decide on a transition plan. Any thoughts, @taion?