react router V5升级至V6探索

938 阅读2分钟

我正在参加「掘金·启航计划」

前言:v6出来也挺久了、最开始因为感觉不够成熟(的错觉)选择了以前最熟悉的v5。最近做个升级才发现升级v6的变化还是很大的

一、简介

首先React Router v6大量使用React钩子,所以在尝试升级到React Router v6之前,你需要使用React 16.8或更高版本。React Router v5兼容React >= 15,所以如果你是v5(或v4),可以升级React而不涉及任何路由器代码。

二、升级步骤

1、升级到React Router v6 

React Router v6大量使用React钩子,所以在尝试升级到React Router v6之前,需要使用React 16.8或更高版本,

升级到@reach/router v1.3.3,

NPM安装@reach/router@latest

// @reach/router v1.2
<Router>
  <User path="users/:userId/grades/:assignmentId" />
</Router>;

function User(props) {
  let {
    // route params were accessed from props
    userId,
    assignmentId,

    // as well as location and navigate
    location,
    navigate,
  } = props;

  // ...
}

// @reach/router v1.3 and React Router v6
import {
  useParams,
  useLocation,
  useNavigate,
} from "@reach/router";

function User() {
  // everything comes from a specific hook now
  let { userId, assignmentId } = useParams();
  let location = useLocation();
  let navigate = useNavigate();
  // ...
}

2、更改路由方式 

v5的路由是包裹在router里面的  升级之前的路由是这样的

import { Routes, Route } from "react-router-dom";

const Routes: FC = () => {
  return (
    <Router>
      <React.Suspense fallback={<PageLoading />}>
        <Switch>
          <Route path="/account" component={OuterLayout} />
          <Route path="/" component={InnerLayout} />
        </Switch>
      </React.Suspense>
    </Router>
  )
}

v6是routers 如下

import { Routes, Route } from "react-router-dom";

<Routes>
  <Route path="/" element={<Home />} />
  {/* ... */}
</Routes>;

3、将Router修改为Routes

// @reach/router
<Router>
  <Home path="/" />
  <NotFound default />
</Router>

// React Router v6
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="*" element={<NotFound />} />
</Routes>

4、修复 Redirect重定向实现与钩子 

之前的重定向都被去除了、, redirectTo或isRedirect 好像都不能使用了

<Router>
  <Home path="/" />
  <Users path="/events" />
  <Redirect from="/dashboard" to="/events" />
</Router>

v6中@reach/router中重定向工作的方式用componentDidCatch“抛出”重定向并捕获它。它会导致整个渲染树停止,然后从新位置开始

// React Router v6
// firebase.json config file
{
  // ...
  "hosting": {
    "redirects": [
      {
        "source": "/dashboard",
        "destination": "/events",
        "type": 301
      }
    ]
  }
}

5、方法更换(这个内容比较多、我也没有完全搞懂、下面列举几个)

useHistory跳转方式(说到这就感觉这方法没必要。全局那么多跳转一个个替换、简直了!)

//v5
import { useHistory } from 'react-router-dom'
const history = useHistory()history.push()
history.goback()

//v6
import { useNavigate } from "react-router-dom";

function useLogoutTimer() {
  const userIsInactive = useFakeInactiveUser();
  const navigate = useNavigate();

  useEffect(() => {
    if (userIsInactive) {
      fake.logout();
      navigate("/session-timed-out");
    }
  }, [userIsInactive]);
}

location

import * as React from 'react';
import { useLocation } from 'react-router-dom';

function App() {
  let location = useLocation();

  React.useEffect(() => {
    // Google Analytics
    ga('send', 'pageview');
  }, [location]);

  return (
    // ...
  );
}

总结: v6升级官方是这么说的

Instead of upgrading and updating all of your code at once (which is incredibly difficult and prone to bugs), the backwards compatibility package enables you to upgrade one component, one hook, and one route at a time by running both v5 and v6 in parallel. Any code you haven't touched is still running the very same code it was before. Once all components are exclusively using the v6 APIs, your app no longer needs the compatibility package and is running on v6. The official guide can be found here.

大概意思就是这次升级比较困难、变化比较大。但是为了未来更好的做兼容才更新的。个人感觉还是有必要去更新的。后面更新迭代大概率是更多基于v6。