Spets Spets - 2 months ago 4
Javascript Question

React: Clean way to re-route user that isn't logged in?

I guess I could always add login in WillTransitionTo which would do a call to the store via Redux to verify that the user is logged in but this seems a bit hacky, especially since since I have to add WillTransitionTo() logic to every single component.

Anyone have any better ideas? I'm going to work toward wiring something into isAuthorized with the onEnter

This is the root root of the application which performs the react-router wire-up.

react-router : 2.0.4

react: 15.0.2

const store = configureStore();


function isAuthorized() {

}

render(
<Provider store={store}>
<Router history={browserHistory}>

<Route path="/" component={Application} onEnter={isAuthorized}>
<IndexRoute component={DashboardPage} />
<Route path="login" component={LoginPage} />
<Route path="dashboard" component={DashboardPage} />
<Route path="items" component={DashboardPage} />
<Route path="item-categories" component={DashboardPage} />
<Route path="modifiers" component={DashboardPage} />
<Route path="taxes" component={DashboardPage} />
<Route path="discounts" component={DashboardPage} />
<Route path="orders" component={DashboardPage} />
<Route path="users" component={DashboardPage} />
</Route>
</Router>
</Provider>,
document.getElementById("application")
);


Note that the example in auth-flow utilizes localStorage to persist userAccess tokens, etc. I really don't want to use localStorage or cookies at this time. I want to minimize the complexity and store the login state in the store(state.user). I don't specifically want to go into the reason for this other than to say that there is a large amount of information that comes the authentication step that needs to be persisted to the store.

Thanks gents!

EDIT: This solution worked for me which is a slight modification on the answer:

function isAuthorized(nextState, replace) {
if (nextState.location.pathname === "/login") {
return;
}
const state = store.getState();
if (state.user && state.user.loggedIn === true) {
return;
}
replace("/login");
}


render(
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={Application} onEnter={(nextState, replace) => isAuthorized(nextState, replace)}>
<IndexRoute component={DashboardPage} />
<Route path="login" component={LoginPage} />
<Route path="dashboard" component={DashboardPage} />
<Route path="items" component={DashboardPage} />
<Route path="item-categories" component={DashboardPage} />
<Route path="modifiers" component={DashboardPage} />
<Route path="taxes" component={DashboardPage} />
<Route path="discounts" component={DashboardPage} />
<Route path="orders" component={DashboardPage} />
<Route path="users" component={DashboardPage} />
</Route>
</Router>
</Provider >,
document.getElementById("application")
);

Answer

You can try doing something like

<Route
  path="/"
  component={Application}
  onEnter={ (nextState, replace) => { isAuthorized(nextState, replace, store) } } >

And in your isAuthorized function

function isAuthorized( nextState, replace, store ) {
  // Now you have access to the store, you can
  const state = store.getState();

  // your logic to validate whether the user is logged in or not
  if ( state.user && state.user.loggedIn === true ) {
    // this user is authenticated
    // continue..
  }
  else {
    // unauthenticated user, redirect the user to login page
    replace({
      pathname: '/login',
      state: { nextPathname: nextState.location.pathname }
    });

  }

}
Comments