React Router v6的使用以及v5升级v6的一些问题

前言 什么是spa?单页和多页的区别?

传统的多页应用: 改变url请求对应的html资源

单页: 单页一次请求所有的资源, 首屏加载会比较慢,后续通过路由切换组件,只需要请求数据

优缺点:

  • 单页首屏渲染耗时多,不利于SEO,页面切换流畅,前后端分离,用户体验好,
  • 多页利于SEO,每次页面切换都要请求资源会对服务器有一定压力,影响用户体验。

单页在经过分片和路由懒加载后性能会好过多页,因此现在的前端工程化项目一般都是使用单页,当项目体量非常庞大的时候再考虑拆分多页。

1. React Router v6

React router官网已经声明v5已经不再维护,那么v6版本相比较v5有哪些变化呢?
作为React生态的工具之一,React Route紧跟React函数组件的步伐,在V6中不再使用 withRouter等class组件的API,所有的API都是以hooks的方式提供。

import { BrowserRouter,Route,Routes,useParams} from ‘react-router-dom’;

安装

yarn add react-router-dom@6

基础使用

function App() {
  return (
  <BrowserRouter>
     <Routes>
       <Route path='/'>
        <Route index element={<Home/>}/>
        <Route path='login' element={<Login/>}/>
        <Route path='about/:id' element={<About/>}/>
        <Route path='*' element={<NotFound/>}/>
        <Route/>
        <Route>
     </Routes>
   </BrowserRouter>
  );
}

function Home(){
  return  <span>Home</span>
}
function Login(){
  return  <span>Login</span>
}
function About(){
  const { id } = useParams();
  return  <span>About: {id}</span>
}
function NotFound(){
  return  <span>NotFound</span>
}

动态路由

function App() {
  return (
    <BrowserRouter>
      <Routes path='/'>
        <Route path='about/:id' element={<About />} />
        <Route />
      </Routes>
    </BrowserRouter>
  );
}

function About() {
  // 参数获取
  const { id } = useParams();
  return <span>About:{id}</span>
}

嵌套路由

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path='/' element={<A />}>
          <Route index path='home' element={<Home />} />
          <Route path='about' element={<About />}>
            <Route path=':id' element={<Info />} />
            <Route index path='dashboard' element={<Dashboard />} />
          </Route>
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

function A() {
  return <span>
    app
    <Outlet />
  </span>
}

function Home() {
  return <span>Home</span>
}

function About() {
  return <span>About
    <Outlet />
  </span>
}

function Info() {
  return <span>info</span>
}

function Dashboard() {
  return <span>Dashboard</span>
}

使用数据渲染路由

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
    children: [
      {
        path: 'login',
        element: <Login />,
        index:true
      },
      {
        path: 'about',
        element: <About />
      }
    ]
  }
])
function App() {
  return (
    <RouterProvider router={router}/>
  );
}


const router = createBrowserRouter(createRoutesFromElements(
  <Route path='/' element={<Home/>}>
  <Route path='/login' element={<Login/>}/>,
  <Route path='/about' element={<About/>}/>,
  </Route>
))
function App() {
  return (
    <RouterProvider router={router}/>
  );
}

使用loader加载数据

import { Outlet, createBrowserRouter, RouterProvider, useLoaderData } from 'react-router-dom';

const requestUser = function () {
  return Promise.resolve({
    id: '001',
    name: 'jack',
    account: '123',
  });
};

async function loader() {
  const user = await requestUser();
  return user;
}

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
    children: [
      {
        path: 'login',
        element: <Login />,
        loader,
      }
    ]
  }
])

function App() {
  return (
    <RouterProvider router={router} />
  );
}

function Home() {
  return <span>Home
    <Outlet />
  </span>
}

function Login() {
  //获取数据 
  console.log(useLoaderData());  //{id: '001', name: 'jack', account: '123'}
  return <span>Login</span>
}

重定向

const requestUser = function () {
  return Promise.resolve({
    id: '001',
    name: 'jack',
    account: '123',
  });
};

async function loader() {
  const user = await requestUser();
  if(!user.id){
    return redirect('/')
  }
  return user;
}

link、navLink
navLink和link类似,唯一的区别是navLinkr提供了link状态相关的属性,可以用来做条件渲染和样式的渲染

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path='/'>
          <Route index element={<Home />} />
          <Route path='about' element={<About />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

function Home() {
  return <span>
    Home
    <Link to='about'>about</Link>
  </span>
}

function About() {
  return <span>
    About
    <Link to='..'>home</Link>
  </span>
}


function Home() {
  return <span>
    Home
    <NavLink to='about'>
      {({ isActive, isPending }) => {
        return isActive ? <span>active </span> : <span>not-active</span>
      }}
    </NavLink>
  </span>
}

function About() {
  return <span>
    About
    <NavLink to='..'>
      {({ isActive, isPending }) => {
        return isActive ? <span>active </span> : <span>not-active</span>
      }}
    </NavLink>
  </span>
}

使用navigate进行跳转

function Home() {
  return <span>
    <Navigate to='/about'></Navigate>
  </span>
}

function Home() {
  const navigate =  useNavigate();
  return <div>
    Home
    <button onClick={()=>navigate('about')}>to about</button>
  </div>
}

错误处理

<Route
  path="/invoices/:id"
  // if an exception is thrown here
  loader={loadInvoice}
  // here
  action={updateInvoice}
  // or here
  element={<Invoice />}
  // this will render instead of `element`
  errorElement={<ErrorBoundary />}
/>;

function Invoice() {
  return <div>Happy {path}</div>;
}

function ErrorBoundary() {
  let error = useRouteError();
  console.error(error);
  // Uncaught ReferenceError: path is not defined
  return <div>Dang!</div>;
}

useParams、useLocation useMatch

function About() {
  const location = useLocation(); // location对象
  const { id } = useParams();

  return <span>
    About:{id}
  </span>
}

2. v5升级v6的一些问题

v5中使用withRouter获取location和history的参数,v6中没有withRouter怎么办呢?

import {
  useLocation,
  useNavigate,
  useParams,
} from "react-router-dom";

function withRouter(Component) {
  function ComponentWithRouterProp(props) {
    let location = useLocation();
    let navigate = useNavigate();
    let params = useParams();
    return (
      <Component
        {...props}
        router={{ location, navigate, params }}
      />
    );
  }

  return ComponentWithRouterProp;
}

取消了v5中route的children和redner属性,使用element属性接受react元素,自定义的属性可以直接添加到元素上。

<Route path=":userId" element={<Profile animate={true} />} />

取消了switch

取消了正则表达式

传送门:
React router官方文档
React Router v5的使用

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值