6

The use case is that I want to map the root (/) to one of two different components based on whether the user is logged in or not, and I want these two components to reside in different bundles and lazily loaded, so simply putting the login check in the render() method would not do.

I tried to use dynamic route definition with require.ensure() to lazily load the component, and it works for the first time, but after changing the login state the component doesn't get updated (even if I navigate to another route and back to / ). I tried to force re-rendering the router by setting props on the component that contains the router, both manually and by making it a Redux connected component, and I also tried to add a listener to the Redux store and change the component state in response to login change, but in all of the attempts I got the error "You cannot change ; it will be ignored" and the component doesn't change.

My ugly solution is to have the different component loading code outside of the router, listen to the login state change and in response load the matching component and set it in the wrapping component's state, which is referenced in the render() code. Is there a clean "React-Router-ish" way to do what I want?

Gabriel
  • 862
  • 6
  • 18

2 Answers2

1

React Router 4 pretty much solves this as it made the route configuration part of the component rendering, so having conditional rendering is the same whether it's based on the location or on other props/state.

Gabriel
  • 862
  • 6
  • 18
0

The closest thing to a clean "React-Router-ish" way to do that is to use the React Router Enterhooks.

An enter hook is a user-defined function that is called when a route is about to be rendered. It receives the next router state as its first argument. The replace function may be used to trigger a transition to a different URL.

So, use the onEnter(nextState, replace, callback?) attribute on your <Route />.

Called when a route is about to be entered. It provides the next router state and a function to redirect to another path. this will be the route instance that triggered the hook.

If callback is listed as a 3rd argument, this hook will run asynchronously, and the transition will block until callback is called.

The general best practice I follow is to place the auth-check flow away from your routes, and place it inside the transition events/hooks.

The usual behavior is - before the route handler actually gets rendered, check the auth, and redirect the user to another route. In your case, if you want to use the same route, but render different components - you should be able to do that using the same technique too. However, that's not a common thing (based on what I've seen), but it should be possible.

For a complete example of this approach, here's the auth-flow code example you can check. It is shared by the creators of React Router, so it looks credible to me.

PS: My answer is valid for React Router versions > 0.13.x.

Community
  • 1
  • 1
Kaloyan Kosev
  • 12,483
  • 8
  • 59
  • 90