2

I'm new on React and I'm facing the error "Uncaught Error: [BrowserRouter] is not a component. All component children of must be a or <React.Fragment>".

I'm trying to do a private route to avoid users to land on the dashboard without being loged on.

PrivateRoute.js

export default function PrivateRoute({ component: Component, ...rest }) {
  const { currentUser } = useAuth()

  return (
    <Route
      {...rest}
      render={props => {
        return currentUser ? <Component {...props} /> : <Route path="/" element={<Navigate to='/login' replace />} />
      }}
    ></Route>
  )
}

App.js

 function App() 
  return( 
        <Container 
        className="d-flex align-items-center justify-content-center" 
        style={{minHeight: "100vh"}}
        >
          <div className="w-100 " style={{ maxWidth: '400px'}}>
            <Router>
              <AuthProvider>
                <Routes>
                  <Route element={<PrivateRoute/>} >
                      <Routes>
                        <Route   path='/' element= {<Dashboard />}/>
                      </Routes>
                  </Route>
                  <Route path="/signup" element={<Signup />}/>
                  <Route path="/login" element={<Login />}/>
                </Routes>
              </AuthProvider>
            </Router>
          </div>
        </Container>
  ) 
} 

I don't know what to do and can't find info about this specific problem, please explain me like I'm 5

1 Answers1

1

I don't see where you render any BrowserRouter component, but do see issue with your PrivateRoute component. You are using it as a layout component but then render neither any passed children or an Outlet for nested routes. There is also no component prop passed to it, so Component results in being undefined. The Route component also doesn't take a render prop function in RRDv6. Since you are wrapping and rendering another Routes component I'll assume you want to render the children prop. Conditionally render the children prop or the Navigate component.

export default function PrivateRoute({ children }) {
  const { currentUser } = useAuth()

  return currentUser ? children : <Navigate to='/login' replace />;
}

Use the PrivateRoute to wrap the children Routes and routes.

<Router>
  <AuthProvider>
    <Routes>
      <Route
        path="*"
        element={(
          <PrivateRoute>
            <Routes>
              <Route path='/' element={<Dashboard />} />
            </Routes>
          </PrivateRoute>
        )} 
      />
      <Route path="/signup" element={<Signup />} />
      <Route path="/login" element={<Login />} />
    </Routes>
  </AuthProvider>
</Router>

Edit react-js-error-uncaught-error-browserrouter-is-not-a-route-component-all

The Router (I'm assuming this is one of the higher-level routers, i.e. BrowserRouter... if you've another router elsewhere in your app, remove it as you need only one router for the entire app), Routes, and Route components in App should all work now. If you've still issue from here we may need to see more of your code.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Thank you so much for your time! I tried your snippet in PrivateRoute.js but now, as I am not rendering, I'm getting "PrivateRoute(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.", how should I render PrivateRoute? I never did something like this before – alvesdaniel Jan 12 '22 at 02:11
  • 1
    @alvesdaniel Oh, I see, you're quite right. I'll update my answer. – Drew Reese Jan 12 '22 at 02:48
  • Thank you so much! One more question, after implementing those changes, I'm getting "No routes matched location "/" ", am I missing something? – alvesdaniel Jan 12 '22 at 03:06
  • 1
    @alvesdaniel Add a path to the route rendering the auth wrapper so it can match `"/"` any other sub-routes. – Drew Reese Jan 12 '22 at 03:49