Search code examples
javascriptreactjswebreach-router

@reach/router nested protected route


I use reach/router with custom protected route like this :

const ProtectedRoute = ({ component: Component, ...rest }) => (
  localStorage.getItem('user_id') ? <Component {...rest} /> : <Redirect from="" to="/login" noThrow />
);

const LoginRoute = ({ component: Component, ...rest }) => (
  localStorage.getItem('user_id') ? <Redirect from="" to="/home" noThrow /> : <Component {...rest} />
);

const PublicRoute = ({ component: Component, ...rest }) => (
  <Component {...rest} />
);

<Router>
  <LoginRoute component={Login} path="/login" />
  <PublicRoute default component={Notfound} />

  <ProtectedRoute component={landingPage} path="/home" />
  <ProtectedRoute path="/" component={App} />
  <ProtectedRoute component={UserList} path="user" />
  <ProtectedRoute component={UserDetail} path="user/create" />
</Router>

i want this to be nested route with user/:id

<ProtectedRoute component={UserList} path="user" />
<ProtectedRoute component={UserDetail} path="user/create" />

what should i do?


Solution

  • I Feel like you're complicating things

    
    const Routes = () => {
      const [loggedIn, setLoggedIn] = useState(false)
    
      useEffect(() => {
        localStorage.getItem('user_id') && setLoggedIn(true)
      }, [])
    
    return (
      <Router>
        <LoginRoute component={Login} path="/login" />
        <Notfound default />
    
        {
          loggedIn 
          ? (
            <>
             <LandingPage path="/home" />
             <App path="/" component={App} />
             <UserList component={UserList} path="user">
               <UserDetail component={UserDetail} path="create" />
             </UserList>
            </>
           ) : (
            <Redirect from="" to="/login" noThrow />
           )
          }
         </Router>
      )
    }
    
    

    In case this didn't work as intended or you feel you want to use it in your way, do this

    
    <Router>
      ...
      <ProtectedRoute component={UserList} path="user">
        <UserDetail path="create" />
      </ProtectedRoute>
    </Router>
    
    

    No need of using ProtectedRoute HOC for UserDetail since it's already nested under ProtectedRoute

    and in UserList use props.children to render UserDetail