关于createBrowserRouter
npm install react-router-dom@6.20.0
新版本出现了createBrowserRouter函数,下面我会结合React.Suspense,loader和路由鉴权来实现一个基本的路由,主要功能是
- 在加载整个页面之前先查看有没有在本地存储
token,然后发请求验证,并且实现自动登录 - 在没有登录的状态下(
redux仓库里面没有存储登录信息),但是本地存储里面有token(可能是错误的token),我进入某个需要鉴权的页面,发送验证登录请求 - 在发送验证登录请求时,用户会发生卡顿,响应到达之后,用户无法看见鉴权页面,而是用
Loading页面替代,等页面加载完成之后,显示页面(也就是说,用户无法在不登录的情况下看见鉴权页面,但是有一段时间的卡顿,不知道如何解决?)
使用
- 首先,在
index.js中导入路由
import router from './router-config/Routes';
// 自动登录逻辑...
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<RouterProvider router={router}></RouterProvider>
);
这好像很奇怪,为什么没有<App />了,那是因为我们把<App />也写到了定义的路由里面
我们只要在<App />里面通过<Outlet />来控制位置即可
- 下面是路由的定义
loader函数里面返回一个数据,可以在响应的组件里面使用useLoaderData()来接收返回值
const loader = async () => {
// 可以先在 redux 里面看看是否存储了 用户信息,如果存在用户信息则不需要发请求,直接返回 null
let resp = (await login()).data
if (!resp) {
return redirect("/home")
}
localStorage.setItem("token", resp)
return resp
}
const LazyLoad = ({ ReactFn }) => {
return (
<>
<Suspense fallback={<Loader />}>
{<ReactFn />}
</Suspense>
</>
)
}
export default createBrowserRouter([
{
path: '/',
element: <App />,
children: [
{
path: '',
element: <RouteBefore />,
children: [
{
path: '/',
element: <Navigate replace to="/home" />
},
{
path: '/home',
element: Home
},
{
path: '/myself',
loader: loader,
element: <LazyLoad ReactFn={MySelf} />
}
]
}
]
}
])
- 下面是关于路由拦截器
const RouteBeforeConfig = [
{path: '/home', needLogin: false},
{path: '/myself', needLogin: true},
{path: /^/about.*/, needLogin: false}
]
export default function RouteBefore() {
const location = useLocation()
const navigate = useNavigate()
const curPath = RouteBeforeConfig.find(it => {
if(typeof it.path === "string") {
return it.path === location.pathname
}
if(it.path instanceof RegExp) {
return it.path.test(location.pathname)
}
}) // 这里的 RouteBeforeConfig 定义了所有的路由跳转是否需要鉴权
let token = localStorage.getItem("token")
if(curPath?.needLogin && !token) {
navigate('/home')
alert("未登录!")
}else {
return (
<>
<Outlet />
</>
)
}
}
- 对于自动登录可以在
main.js中发送,然后再保存到仓库里面