在网路上查找相关文章的时候,发现很多用法已经淘汰了,所以就自己整理这篇来当作笔记。
现在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 similarThe routes would look as such:
<Routes> <Route path="/bossHome" element={( <NoNavbarLayout> <BossHomePage /> </NoNavbarLayout> )} /> <Route path="/home" element={( <NavbarLayout> <Home /> </NavbarLayout> )} /></Routes>
参考资料:
临时找不到原本参考的那篇,找到了再补上来