Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirecting user based on state in React

Right now, my router looks like this:

<Router history={browserHistory}>
    <Route component={Provider}>
        <Route path="/" component={AppPage}>
            <Route path="login" component={LoginPage}/>
            <Route component={LoggedinPage}>
                <Route path="onboarding" component={OnboardingPage}/>
                <Route component={OnboardedPage}>
                    <IndexRoute component={HomePage}/>
                    <Route path="settings" component={SettingsPage}/>
                </Route>
            </Route>
        </Route>
    </Route>
</Router>

LoggedinPage redirects to /login if the user isn't logged in and OnboardedPage redirects to /onboarding if the user hasn't completed the onboarding flow (choosing username, etc). However, I think more of these conditional redirects may be needed in the future. What's the best way to handle these conditional redirects? Is it possible to have a single component that handles all the redirects?

like image 658
Leo Jiang Avatar asked Nov 08 '22 17:11

Leo Jiang


1 Answers

<Route>s accept an onEnter hook that is called when the route matches. A hook would look something like this:

function requireAuth(nextState, replace) {
    if (!loggedIn()) {
        replace({ pathname: 'login' });
    }
}

Then use it like so:

<Route path="/" component={AppPage}>
    <Route path="home" component={HomePage} onEnter={requireAuth}/>
    <Route path="login" component={LoginPage}/>
</Route>

A more composable example, that lets you combine multiple checks:

function checkAuth() {
    if (!loggedIn()) {
        return { pathname: 'login' };
    }
}

function checkOnboarding() {
    if (!completedOnboarding()) {
        return { pathname: 'onboarding' };
    }
}

function redirect(...checks) {
    return function(nextState, replace) {
        let result;
        checks.some(check => {
            result = check();
            return !!result;
        });
        result && replace(result);
    };
}

Then combine away!

<Route path="/" component={AppPage}>
    <Route path="home" component={HomePage}
        onEnter={redirect(checkAuth, checkOnboarding)}/>
    <Route path="login" component={LoginPage}/>
    <Route path="onboarding" component={OnboardingPage}
        onEnter={redirect(checkAuth)}/>
</Route>
like image 121
David Tang Avatar answered Nov 14 '22 21:11

David Tang