0

I had a similar question but this time the problem is a bit different. So I have an authorization component "Login". And when the user logs in it should redirect to the home page. Otherwise if there isn't any user logged in, it redirect to the login page.

My PrivateRoute.jsx looks like this:

const PrivateRoute = ({component: Component, ...rest}) => {
    const { user } = useContext(AuthContext);
    const navigate = useNavigate();
  return (
      <Route
    {...rest}
    exact
    render={(props => user ? <Component {...props}/> :  <Navigate replace to="/login" />)}
    />
  )
}

So as you see it accepts props and also the user.

And my App.js:

function App() {

  return (
    <AuthProvider>
        <BrowserRouter>
    <Navbar/>
        <Routes>
          <Route exact path="/register" element={<Register/>}/>
          <Route exact path="/login" element={<Login/>}/>
          <PrivateRoute exact path="/" element={<Home/>}/>
        </Routes>
    </BrowserRouter>
    </AuthProvider>
  );
}

So as you see I added PrivateRoute along with other routes, but for some reason I have an error:

[PrivateRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

So I closed the PrivateRoute like this:

<>
  <PrivateRoute exact path="/" element={<Home/>}/>
</>

But it doesn't solve the problem. I need to redirect to the Login page if the user isn't logged in and to the Home is he's logged in.

Carl
  • 345
  • 5
  • 23

2 Answers2

1

In react-router 6, <Routes> only supports having <Route> as its children. <PrivateRoute> may render a <Route> internally, but that's not enough. You'll need to redesign your PrivateRoute component so that it can be placed inside the element prop:

const PrivateRoute = ({ children }) => {
  const { user } = useContext(AuthContext);
  return user ? children : <Navigate replace to="/login"/>
}

// used like:
<Routes>
  <Route exact path="/register" element={<Register/>}/>
  <Route exact path="/login" element={<Login/>}/>
  <Route exact path="/" element={<PrivateRoute><Home/></PrivateRoute>}/>
</Routes>
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • thank you, good sir! you helped me a second time with my routes. so i can pass props through `PrivateRoute` to my `Home` component too? – Carl May 25 '22 at 13:32
  • If you have some props you want to forward on, yes, you can do that. However, I think you may be used to how react-router 5 does things. In react-router 6, the `Route` is not going to pass any props to its children. So Route won't pass props to Register, Login, PrivateRoute, or Home. Since PrivateRoute isn't receiving any props, it's not going to have anything to pass on to Home. In react 6, the standard way to get things like `history` or `match` is for the child component (``) to use hooks like `useMatch()`. – Nicholas Tower May 25 '22 at 13:38
  • See [upgrading from v5](https://reactrouter.com/docs/en/v6/upgrading/v5) – Nicholas Tower May 25 '22 at 13:39
0

In PrivateRoute.jsx you are expecting prop named as component, but in App.js you are passing as

<PrivateRoute exact path="/" element={<Home/>}/>

Try changing this to

<PrivateRoute exact path="/" component={<Home/>}/>

or do this

const PrivateRoute = ({element: Component, ...rest}) => {
//... rest of code
}