I'm new to react-router (and client side routing in general) so I might be thinking about this all wrong. Sorry in advance if that is the case...
Basically just want to implement 3 simple rules:
I keep track of the user in this.state.user
. My current router seems to follow the first 2 rules, but only lets the authenticated user see the home page ('/profile' redirects to '/') so I know I'm doing something wrong but can't figure out what.
<Router>
{this.state.user ? (
<Switch>
<Route path="/" exact component={Home}/>
<Route path="/profile" exact component={Profile}/>
<Route render={() => (<Redirect to="/" />)}/>
</Switch>
) : (
<Switch>
<Route path="/login" exact component={Login}/>
<Route render={() => (<Redirect to="/login" />)}/>
</Switch>
)}
</Router>
Any advice is appreciated. Thank you
For anybody arriving here looking for how to redirect if none of the routes matches:
<Switch>
// ... your routes
<Route render={() => <Redirect to="/" />} />
</Switch>
Note that the routes have to be direct children of the <Switch>
, e.g. this doesn't work:
<Switch>
<Fragment>
// ... your routes
<Route render={() => <Redirect to="/" />} />
</Fragment>
</Switch>
(maybe fixed in more recent versions of react-router)
The answer is simple
<Switch>
<Route path="/login" exact component={Login}/>
{!this.state.user && <Redirect to='/login' />}
<Route path="/" exact component={Home}/>
<Route path="/profile" exact component={Profile}/>
<Redirect to="/" />
</Switch>
The main difference between switch and router is that router will try to execute all matched path and append content together, switch will stop on the first match.
My app has a similar approach, but I wrapped protected routed on a separate file, then wrap the user profile as HOC
export const App = () => (
<Switch>
<Route exact path='/login' component={Login} />
{!hasToken() && <Redirect to='/login' />}
<Route path='/' component={ProtectedRoute} />
</Switch>
)
protectedRoute.js
const ProtectedRoute = ({ userInfo }: Props) => (
<Layout userInfo={userInfo}>
<Switch>
<Route exact path='/a' component={A} />
<Route exact path='/b' component={B} />
<Route path='/c' component={C} />
<Redirect to='/a' />
</Switch>
</Layout>
)
export default withUserInfo(ProtectedRoute)
Have you thought about using a Route
wrapper that checks for a user when a user is necessary for the Route
?
const CanHasRouteAccess = ({ component: Component, iHasUser, ...rest }) => {
return iHasUser ? (
<Route {...rest} render={props => <Component {...props} />} />
) : (
<Redirect to="/" />
);
};
You could pass the props to the Route or cause a redirect to the home page when there isn't a user.
<CanHasRouteAccess
path="/personal-data"
exact
component={Profile}
iHasUser={Boolean(user)}
/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With