开发者问题收集

如何修复升级到 react-router v6 后出现的错误

2021-12-06
2495

在升级到 v6 之前,我有这部分代码,它运行正常:

//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>
    )

升级后,我只将 Switch 更改为 Routes ,将 component 更改为 element ,并希望它能正常工作,但事实并非如此。

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>.

尝试了很多方法,但都无济于事。我怎样才能让它像升级前一样工作?

//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>
    )
1个回答

实际上, BrowserRouter 呈现的 Route 需要包装在 Routes 组件中,并在 element prop 上呈现 JSX 或包装子 React 组件。

它似乎是一个布局组件,因此将其抽象为自己的组件,该组件为嵌套的 Route 组件呈现 Outlet 。如果 Sidebar 不是使用 React 钩子的函数组件,则使用布局组件中的钩子并像以前一样将它们作为 props 传递给 Sidebar 。请注意,如果 Sidebar 以前使用过 history 对象,那么它在 RRDv6 中已被 navigate 函数取代。

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>
)
Drew Reese
2021-12-06