I am trying to setup a new front-end project using react, react-router and redux and I'm stumbling on setting up a login workflow that works well and with many pages.
Here is the logic that I want to have:
- Have a variable in the redux store that says if I'm logged in or not. To simplify let's say that we have
logged: true/false. - When
loggedis set to true from the login page, redirect to the page we were redirected from, or redirect to/if not defined. The previous location is stored innextPathname. - When
loggedis set tofalsein a component that requires auth, redirect to/.
My main problem with this workflow is that I want to dispatch an action (set the logged value) and then do a redirection.
Here are a few alternatives that I have explored:
- Check if
logged==truein my login component'scomponentWillReceivePropsand redirect if it's the case. This works well for the login workflow but if I have to implement such a logic for the logout component, I have to do it for each component that requires auth. (Mixins don't work thanks to ES6 react components...). - Handle the redirections in a middleware: when the action is about login, run the action and then redirect. However I don't know if this is a best practice or not.
So my question is: how do I make the auth work without too much overhead on all pages that are restricted?
A bit of code:
app.js:
function requireAuth(nextState, replace) {
if(store.getState().Login.logged === false) {
replace({
pathname: "/login",
state: { nextPathname: nextState.location.pathname }
});
}
}
const history = syncHistoryWithStore(browserHistory, store);
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={Archives} onEnter={requireAuth}></Route>
<Route path="/login" component={LoginComponent}></Route>
</Router>
</Provider>,
document.getElementById("app")
);
The LoginComponent:
class LoginComponent extends React.Component<LoginProps, any> {
componentWillReceiveProps(newProps) {
if(newProps.logged) {
let nextPath = "/";
const {location, history} = newProps;
if (location.state && location.state.nextPathname) {
nextPath = location.state.nextPathname;
}
history.pushState({}, nextPath);
}
}
render() {
return <div>This is a login form</div>
}
}