Closed rightaway closed 8 years ago
Seems like it was being caused by a wrong implementation of requireAuth on my part. Which leads me to the question how can I get the redux application state in onEnter? onEnter is passed 3 arguments, but inspecting them in the console it looks like none of them contain the application state (like the stuff you'd access in react components through this.props
).
Hmmm, how are u passing routes down to ReduxRouter?
I am also having the same problem but triggered by something else.
const createStoreWithMiddleware = compose(
// ...
reduxReactRouter({ routes, createHistory }),
// ...
)(createStore);
I got it from the samples here. But I'm no longer getting the error you described in #67 because that was coming from a requireAuth that was actually just doing a console.log to see what arguments get passed in, but wasn't doing anything else.
But I'm still wondering how to get redux state in onEnter so that I can do the right thing based on the current state.
use getRoutes({ dispatch, getState })
api:
see: https://github.com/rackt/redux-router/issues/68#issuecomment-141903408
but there is a bug blocking this usage, see: #62
@chentsulin, thanks, do you have an example that shows how to use that code snippet you provided in that comment? I can't tell where and how to use it.
I'm with @rightaway. Could use an example.
I'm trying to use the declarative syntax to define our app's routes:
<ReduxRouter>
<Route path={HOME} name="Home" component={Home}>
<Route path={LOGIN} name="Login" component={Login} />
<Route path={SERVICE} name="Service" component={Service} onEnter={requireAuth} />
</Route>
</ReduxRouter>
It would be ideal if the onEnter
hook were invoked with getStore
as well as the nextState, replaceState, etc argument, ie:
function requireAuth({ getStore, nextState, replaceState }) {
if (getStore().auth.grant.expired) {
// redirect back to login.
replaceState({ nextPathname: nextState.location.pathname }, LOGIN)
}
}
@AndrewKarasek ea
You can wrap your routes in a function that accepts the store object and provide this as the getRoutes parameter in your store create function. Example:
function getRoutes({ dispatch, getState }) {
function onEnter(nextState, state) {
// You should now have access to both dispatch and getState
}
return (
<Route path="/" component={ App }>
<Route path="dashboard" component={ Dashboard } onEnter={ onEnter } />
</Route>
);
}
const finalCreateStore = compose(
applyMiddleware(...middleware),
reduxReactRouter({
getRoutes,
history,
})
)(createStore);
This example provided by @jvanleeuwen is working like a charm for me. Thanks!
@jvanleeuwen I'm getting Uncaught ReferenceError: store is not defined(…)
in my onEnter
function while following that pattern. Any ideas as to why that'd be the case? (I can post more info about my setup if you need)
@stevenleeg Unfortunately I have this issue too. For now you can use the links and work @chentsulin (thanks) did in #62 to get around this. Seems like the store is not fully created when getRoutes is called
I'm also having this issue. Using the workaround, going to a disallowed route renders the disallowed route before redirecting, which is not acceptable behavior. @stevenleeg @jvanleeuwen are you also seeing that?
@nhagen What happens when you turn the behaviour around.. Render the allowed route and when a authentication is successful redirect to the (no longer) disallowed route
@jvanleeuwen didn't have time to try that sadly. As a workaround, @mjrussell suggested in discord to handle onEnter
in componentWillMount
, which is more reliable at this point, so I'm running with that.
edit: actually, this runs into the same issue--the component finishes the inital render cycle before transitioning :(
Also, @steveoland wrote a helper for react-redux-universal-hot-example
that addresses this problem in their project.
i was using the above, but just "skipping" the onEnter
handler if the store isn't defined doesn't work if the onEnter
hook is an auth check. this doesn't seem to be an issue in the above link, but i'm also not doing server side rendering yet.
yeah I'm running into that same issue trying to implement the helper in my project, unfortunately.
any other ideas/fixes? this issue has been driving me nuts for the last few days.
:) me too.
aside from fixing this: https://github.com/rackt/redux-router/pull/62 i'm not really sure.
I think I'm close to something here. Try using the setTimeout
method along with the third argument to onEnter
handlers: callback
which will only permit the transition to proceed when called. For example:
const requireAuth = (nextState, replaceState, callback) => {
setTimeout(() => {
console.log('requireAuth')
function checkAuth() {
console.log('checkAuth')
const { auth } = store.getState()
if (!auth.get('currentUser')) {
replaceState({}, '/auth/login')
}
callback()
}
const { auth } = store.getState()
if (!auth.get('loaded')) {
AuthActions.initCurrentUser().then(checkAuth).catch(checkAuth)
} else {
checkAuth()
}
}, 0)
}
This is mostly working but now I'm running into #67 warnings /sigh
So I looked through my code and the only place I was leveraging ReduxRouter was to grab route parameters in selectors within connect
. With reselect 2.0.0, you can accesss the props of the component: https://github.com/rackt/reselect#accessing-react-props-in-selectors. The places I need access to the parameters are all route handlers, which have params
passed as a prop via: https://github.com/rackt/react-router/blob/master/docs/API.md#handler-components.
ideally everythign is flowing through redux via redux-router, but until onEnter
is guaranteed to have the store, i'm ok relying on the above even though its a little messier.
@stevenleeg setTimeout
and callback
fixed the issue for me too. Cleanest workaround so far.
@kromit a setTimeout isn't a great solution and create an async flow that could cause problem in case of rehydratetion...
Consider to do this instead: https://github.com/rackt/redux-router/pull/62#issuecomment-155836940
@rightaway can you check if the original warning are gone with pull-request #202 ?
When I add the onEnter to a route, I get several errors about ReduxRouterContext and the page doesn't load.