Home > other >  How to fix error which appeared after upgrading to react-router v6
How to fix error which appeared after upgrading to react-router v6

Time:12-07

Before upgrading to v6 I had this part of code, which worked as it should:

//before
return (
        <BrowserRouter>
            <Route render={(props) => (
                <div className={`layout ${themeReducer.mode}`}>
                    <Sidebar {...props}/>
                    <div className="layout__content">
                        <TopNav/>
                        <div className="layout__content-main">
                            <Switch>
                                <Route path='/' exact component={Dashboard} />
                                <Route path='/activity' component={Activity} />
                            </Switch>
                        </div>
                    </div>
                </div>
            )}/>
        </BrowserRouter>
    )

After upgrading I only changed Switch to Routes and component to element and expected it to work, but it didn't.

Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.

Tried many things, but nothing helped. How can I make it work the way it worked before the upgrading?

//after
return (
        <BrowserRouter>
            <Route render={(props) => (
                <div className={`layout ${themeReducer.mode}`}>
                    <Sidebar {...props}/>
                    <div className="layout__content">
                        <TopNav/>
                        <div className="layout__content-main">
                            <Routes>
                                <Route path='/' element={<Dashboard/>} />
                                <Route path='/activity' element={<Activity/>} />
                            </Routes>
                        </div>
                    </div>
                </div>
            )}/>
        </BrowserRouter>
    )

CodePudding user response:

Actually, the Route rendered by BrowserRouter needs to be wrapped in a Routes component and also render JSX on the element prop or wrap a child React component.

It appears to be a layout component so abstract it out into its own component that renders an Outlet for the nested Route components. If Sidebar isn't a function component to use the React hooks then use the hooks in the layout component and pass them as props to Sidebar as before. Note that if Sidebar previously used the history object that it was replaced by a navigate function in RRDv6.

import { Outlet, useLocation, useMatch, useNavigate } from 'react-router-dom';

const Layout = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const match = useMatch();
  // ... etc....

  return (
    <div className={`layout ${themeReducer.mode}`}>
      <Sidebar 
        location={location}
        match={match}
        navigate={navigate}
        ...... etc....
      />
      <div className="layout__content">
        <TopNav/>
        <div className="layout__content-main">
          <Outlet /> // <-- nested routes render here
        </div>
      </div>
    </div>
  );
};

...

return (
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<Layout />} >
        <Route index element={<Dashboard />} />
        <Route path="/activity" element={<Activity />} />
      </Route>
    </Routes>
  </BrowserRouter>
)
  • Related