本篇文章记录了useRoutes第一个参数的使用方法,暂不涉及第二个参数。


一、使用位置

一开始以为可以像react-router-config那样使用,于是写成

import { BrowserRouter as Router, useRoutes } from 'react-router-dom';

const SetRoutes = () => {
  const routes = useRoutes([
    {
      path:'/',
      element: <div>...</div>
    },
    {
      path:'/a', 
      element: <div>aaa</div>
    }
  ]);
  return (
    <Router>
      {routes}
    </Router>
  )
}

结果报错useRoutes() may be used only in the context of a <Router> component.
啥?这不是已经包裹在<Router>中了吗。
看过其他例子后才知道,需要将使用了useRoutes的整个组件都放入<Router>当中,就像下面这样

import { BrowserRouter as Router, useRoutes } from 'react-router-dom';

const GetRoutes = () => {
  const routes = useRoutes([
    {
      path:'/',
      element: <div>...</div>
    },
    {
      path:'/a', 
      element: <div>aaa</div>
    }
  ]);
  return routes;
}

const SetRoutes = () => {
  return (
    <Router>
      <GetRoutes />
    </Router>
  )
}

二、嵌套路由

嵌套路由就是在有子路由的路由中设置children,例如:

import { 
  BrowserRouter as Router, 
  Outlet, 
  useRoutes 
} from 'react-router-dom';

const GetRoutes = () => {
  const routes = useRoutes([
    {
      path:'/',
      element: <div>...</div>
    },
    {
      path:'/a', 
      element: <><div>aaa</div><Outlet></>,
      children: [
        {
          path: 'b', // 这里的path,写为'/b',也可以  /加不加都行
          element: <div>bbb</div>
        }
      ]
    }
  ]);
  return routes;
}

const SetRoutes = () => {
  return (
    <Router>
      <GetRoutes />
    </Router>
  )
}

上面的代码相当于

import { 
  BrowserRouter as Router, 
  Outlet, 
  Routes,
  Route
} from 'react-router-dom';

const SetRoutes = () => {
  return (
    <Router>
      <Routes>
        <Route path='/' element={<div>...</div>} />
        <Route path='/a' element={<><div>aaa</div><Outlet /></>} >
          <Route path='b' element={<div>a-bbb</div>} />
          // 或者写为<Route path='/a/b' element={<div>a-bbb</div>} />
        </Route>
      </Routes>
    </Router>
  )
}

三、分模块管理

如果项目比较大,可能很多页面共用一段相同的路径,但是又不是嵌套路由的关系,每次往useRoutes添加路由都要写完整的path感觉麻烦怎么办?
就比如一个项目通常分为前台页面和后台页面,我们可以将前台页面和后台页面分开来管理,例如:

import { 
  BrowserRouter as Router, 
  useRoutes 
} from 'react-router-dom';
import RecLayout from 'xxxx';
import AdminLayout from 'xxxx';

const GetRecRoutes = () => { // 获取前台路由
  const routes = useRoutes([
    {
      path:'',
      element: <RecLayout />,
      children: [
        {
          path: '',
          element: <div>前台首页</div>
        },
        {
          path: 'a',
          element: <div>rec-aaa</div>
        }
      ]
    },
    {
      path: '*',
      element: <div>前台404</div>,
    }
  ]);
  return routes;
}

const GetAdminRoutes = () => { // 获取后台路由
  const routes = useRoutes([
    {
      path:'',
      element: <AdminLayout />,
      children: [
        {
          path: '',
          element: <div>后台首页</div>
        },
        {
          path: 'a',
          element: <div>admin-aaa</div>
        },
      ]
    },
    {
      path: '*',
      element: <div>后台404</div>,
    }
  ]);
  return routes;
}

const GetAllRoutes = () => {
  const routes = useRoutes([
    {
      path: '/*',
      element: <GetRecRoutes />,
    },
    {
      path:'/admin/*',// 末尾的 /* 必不可少
      element: <GetAdminRoutes />,
    },
    {
      path: '*', // 这个404页面不会被匹配到
      element: <div>404</div>,
    }
  ])
  return routes;
}

const SetRoutes = () => {
  return (
    <Router>
      <GetAllRoutes />
    </Router>
  )
}

注意事项

1、因为前台页面的path我写为了'/*',所以404页面得在前后台的useRoutes中分别添加,否则遇到没有页面的路径,也会匹配到前台的路由当中,从而显示空白页面
2、拿后台路由举例,path'/admin/*'末尾的'/*'必不可少,否则后台路由只会精确匹配到/admin路径,访问/admin/a将不会匹配到后台路由而是进入前台路由当中,而前台路由又没有相对应的页面,将会展示404页面
3、这里即使我将'/admin/*'放在'/*'后面,在访问/admin时,依然会匹配到后台的页面


目前暂时只对useRoutes的第一个参数进行学习,之后有空的话会抽空继续学习第二个参数的用法。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐