React Router v6为何需在父组件而非子路由组件包裹BrowserRouter
关于react-router-dom@6中useRoutes与BrowserRouter的使用问题
问题场景
使用react-router-dom@6.4.1的useRoutes钩子配置路由时,最初将BrowserRouter放在路由组件内部包裹useRoutes的返回结果,导致报错;将BrowserRouter移到父组件(app.jsx)中包裹路由组件后问题解决,疑惑其中原因。
初始routes.jsx代码
import { useRoutes } from "react-router-dom"; import TestPage from "../Pages/Public/TestPage"; import TestPageTwo from "../Pages/Public/TestPageTwo"; const redirectRoutes = [ { path: "/no-match", element: () => <div>No Match found</div>, }, ]; const Router = () => { const router = useRoutes([ { path: "/testPage", element: <TestPage />, loader: false, }, { path: "/testPageTwo", element: <TestPageTwo />, loader: false, }, ...redirectRoutes, ]); return <BrowserRouter>{router}</BrowserRouter>; }; export default Router;
初始app.jsx代码
import { Provider } from "react-redux"; import Router from "./Router"; import initializeStore from "./Reducer/initializeStore"; import "./App.css"; export const store = initializeStore(); const App = () => { return ( <Provider store={store}> <Router /> </Provider> ); }; export default App;
触发的错误
Uncaught Error: useRoutes() may be used only in the context of a
component.
修正后的app.jsx代码
import { Provider } from "react-redux"; import { BrowserRouter } from "react-router-dom"; import Router from "./Router"; import initializeStore from "./Reducer/initializeStore"; import "./App.css"; export const store = initializeStore(); const App = () => { return ( <Provider store={store}> <BrowserRouter> <Router /> </BrowserRouter> </Provider> ); }; export default App;
原因说明
react-router-dom的所有路由相关钩子(包括useRoutes)都依赖**Router组件提供的上下文(Context)**才能正常工作。
在最初的写法里,useRoutes是在Router组件的函数体内先执行的,而BrowserRouter是在useRoutes执行完毕后才被渲染到组件树中——这意味着调用useRoutes时,当前组件树中还不存在任何Router上下文,钩子无法获取到必要的路由环境信息,因此抛出错误。
必须保证调用useRoutes的组件,处于BrowserRouter(或其他Router类型组件,如HashRouter)的包裹之下,这样钩子执行时才能读取到路由上下文。将BrowserRouter移到app.jsx中作为父组件,让Router组件成为它的子元素,就能满足这个上下文依赖要求。
内容的提问来源于stack exchange,提问作者Akshay Padinjarethadathil
相关产品推荐
相关产品推荐

