React-Router-Dom v6版本 与 旧版的差异範例

在网路上查找相关文章的时候,发现很多用法已经淘汰了,所以就自己整理这篇来当作笔记。

现在react-router-dom v6 版本改了很多,例如:

不再支援在route内使用客製化component,也就是说无法直接引用Layout。也不支援Switch,需要改用routes,并且改用"element"作为Component引入点。如果要在使用Link的时候传递参数,正常的props是无法使用的 (我理解是这样,不太确定是否正确),要改用state传递,而被呼叫的Component要使用useLocation来接。

以下将重大差异的部份个别列出。

1. this.props.match在DOM v6由useLocation、useParams取代

DOM v6之前

之前的定义: 在每一个Route判断到网址的路径相符,要渲染该组件时都会将物件match给传进该组件中。

也因为以上特性,所以早期很多人写法都是直接从match取得参数:

const NotePage = ({match}) => {let noteId = match.params.id}

另外在DOM v6之前也有人使用match取得path:

import React from "react"import { Route, Link } from "react-router-dom"class About extends React.Component {    render() {        //在Route将组件渲染时,会传入match物件,在这里把它印出来        console.log(this.props.match)        return (            <div>                <h2>关于我们选单</h2>                <ul>                    {/*url是match的属性之一,会回传网址列的路径*/}                    <li><Link to={`${this.props.match**.url**}`}>理念介绍</Link></li>                    <li><Link to={`${this.props.match.url}/his`}>历史沿革</Link></li>                </ul>                {/*path也是match的属性之一,会回传透过哪个Route进入的path属性*/}                <Route exact path={`${this.props.match**.path**}`} component={Introd} />                <Route path={`${this.props.match.path}/his`} component={His} />            </div>        )    }}

DOM v6之后

取得参数部分,由useParams取代,如下:

const NotePage = () => {let {id} = useParams();}

如果要取得现在的URL,则变成是要用useLocation():

const location = useLocation();console.log(location.pathname);

Here are the properties it returns:

The hash:  Returns the anchor part of the current page.The pathname:  Returns the path of the current page.The search:  Returns the query part of the current page.

2. Redirect Component在DOM v6中被Navigate Component取代

DOM v6之前

在DOM v5版本中我们可以使用Redirect Component强制转导,

概念为:

class About extends React.Component {    render() {        return (<div>                <Switch>                    <Route exact path={`${this.props.match.path}`} component={Introd} />                    <Route path={`${this.props.match.path}/his`} component={His} />//...                    <Redirect from={`${this.props.match.path}/story`} to={`${this.props.match.url}/his`} />                </Switch>            </div>        )    }}

from意思是当目前的Link连结到${this.props.match.path}/story这个路径的时候,Redirect会将网址重新转到${this.props.match.url}/his上。

Redirect的to属性具体如下:

<Redirect from={`${this.props.match.path}/story`}             to={{pathname:`${this.props.match.url}/his`                ,search: "?hey=UCCU"                ,state:{name:'Referrer'}}} />

DOM v6之后

React 是 React Router v6 中新引入的组件,其作用与已弃用的 组件相同。

我们可以使用导航组件声明重定向,如下所示:

<Navigate to="/somewhere/else" />

鉴于我们希望在用户访问我们应用程序上的无效 URL 时将用户重定向到 home 组件,我们可以这样编写导航代码:

<Routes>  <Route path='/' element={<h1>Home Page Component</h1>} />  <Route path='/login' element={<h1>Login Page Component</h1>} />    // New line  <Route path='*' element={**<Navigate to='/' />**} /></Routes>

3. useHistory在DOM v6中被useNavigate取代

DOM v6之前

useHistory 钩子是React Router Dom v5中的一个函数,它使我们能够访问浏览器History Stack实例。

useHistory 可用于从当前位置 导航到新位置 或 返回到特定位置。

import { useHistory } from "react-router-dom";import "./App.css"; function App() {  const history = useHistory();   const handleGoBack = () => {    history.goBack();  };  return (    <>      <button onClick={handleGoBack}>Go Back</button>    </>  );} export default App;

从上面的代码中,我们使用 useHistory hook中的 goBack() 方法来建立 回上一页按钮功能。

我们还可以使用 useHistory Hook重定向到新路径,如下所示:

import { useHistory } from "react-router-dom";import "./App.css"; function App() {  const history = useHistory();   const handleGoHome = () => {     history.push("/home"); // New line   };  return (    <>      <button onClick={handleGoHome}>Go Back</button>    </>  );} export default App;

DOM v6之后

useHistory 在 React Router v6 中也被弃用,取而代之的是 useNavigate。

useNavigate 允许我们在函数内以编程方式导航路径,它採用与 组件相同的props,并且与 useHistory 具有相同的目的。

例如我们使用useNavigate()模拟用户登录时重定向到登录页面:

import { useEffect, useState } from "react";import { Navigate, Route, Routes, useNavigate } from "react-router-dom";import "./App.css"; function App() {  const navigate = useNavigate();  const [isLoggedIn, setisLoggedIn] = useState(false);   useEffect(() => {    // Checking if user is not loggedIn    if (!isLoggedIn) {      navigate("/");    } else {      navigate("/login");    }  }, [navigate, isLoggedIn]);   return (    <>      <Routes>        <Route path='/' element={<h1>Home Page Component</h1>} />        <Route path='/login' element={<h1>Login Page Component</h1>} />        <Route path='*' element={<Navigate to='/' />} />      </Routes>       {/* New line */}      {isLoggedIn || (        <button onClick={() => setisLoggedIn(true)}>Log me in</button>      )}    </>  );} export default App;

如上範例,官方倾向于建议在useEffect()中使用useNavigate。

另外,由于能够操作浏览器History Stack,因此也能做到重定向到上一页:

import { useNavigate } from "react-router-dom";import "./App.css"; function App() {  const navigate = useNavigate();   const handleGoBack = () => {     navigate(-1); // new line  };  return (    <>      <button onClick={handleGoBack}>Go Back</button>    </>  );} export default App;

4. Link传递props参数问题

Pass props in Link react-router

上面这篇讨论很多解法

但我自己试成功是使用官网範例:

https://reactrouter.com/en/6.8.0/components/link#state

The state property can be used to set a stateful value for the new location which is stored inside history state. This value can subsequently be accessed via useLocation().

<Link to="new-path" state={{ some: "value" }} />

You can access this state value while on the "new-path" route:

let { state } = useLocation();

5. 在Route中加入Layout的问题

In react-router-dom v6 there is no longer a use case/allowance for custom route components. Only Route (or Fragment) components can be children of the Routes component. The layout components are rendered on a Route component's element prop and they can render children components or Outlets if they are wrapping nested Route components.

Given a layout components rendering a children prop *:

const NoNavbarLayout = ({ children }) => (  <div className="login-layout">    <p>No navbar</p>    {children}  </div>);
I am assuming the NavbarLayout component is similar

The routes would look as such:

<Routes>  <Route    path="/bossHome"    element={(      <NoNavbarLayout>        <BossHomePage />      </NoNavbarLayout>    )}  />  <Route    path="/home"    element={(      <NavbarLayout>        <Home />      </NavbarLayout>    )}  /></Routes>

参考资料:
临时找不到原本参考的那篇,找到了再补上来


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章