2021 react-router v6 快速入门

使用官方的教学项目

npx create-react-app router-tutorial

安装 react-router 依赖

cd router-tutorial
npm add react-router-dom@6 history@5

react-router-dom是浏览器端的基于react-router库的库,所以装了这个以后就不用再手动装react-router了

修改App.js和 index.js到简单的样子

//src/App.js
export default function App() {
  return (
    

Bookkeeper!

); }
// src/index.js
import { render } from "react-dom";
import App from "./App";

const rootElement = document.getElementById("root");
render(, rootElement);

然后启动项目,然后我们可以在基础上修改了。

# probably this
npm start

# or this
npm run dev

#or
yarn start

01.BrowserRouter

连接你的app到浏览器的URL。

用BrowserRouter包裹在你的App的外面

//src/index.js
import { render } from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";

const rootElement = document.getElementById("root");
render(
  
    
  ,
  rootElement
);

02.添加一些链接Link

src/App.js里添加一些链接和全局导航。

import { Link } from "react-router-dom";

export default function App() {
  return (
    

Bookkeeper

); }

现在点击那些链接,你会发现地址栏会发生改变,也可以用前进后退在历史记录中移动

03.添加一些路由

  • src/routes/invoices.jsx
  • src/routes/expenses.jsx
//src/routes/expenses.jsx
export default function Expenses() {
  return (
    

Expenses

); }
//src/routes/invoices.jsx
export default function Invoices() {
  return (
    

Invoices

); }

接下来我们需要在index.js里面创建路由配置告诉app如何渲染不同的url

//src/index.js
import { render } from "react-dom";
import {
  BrowserRouter,
  Routes,
  Route
} from "react-router-dom";
import App from "./App";
import Expenses from "./routes/expenses";
import Invoices from "./routes/invoices";

const rootElement = document.getElementById("root");
render(
  
    
      } />
      } />
      } />
    
  ,
  rootElement
);

04.嵌套路由

我们注意到点击链接的时候,App中的布局消失了。只剩下Expenses或Invoices这两个路由指向的内容

嵌套路由的作用就是共享部分UI

我们需要两步操作实现这一点

首先index.js里面对路由进行嵌套。这样两个组件就变成了App组件的子节点

import { render } from "react-dom";
import {
  BrowserRouter,
  Routes,
  Route
} from "react-router-dom";
import App from "./App";
import Expenses from "./routes/expenses";
import Invoices from "./routes/invoices";

const rootElement = document.getElementById("root");
render(
  
    
      }>
        } />
        } />
      
    
  ,
  rootElement
);

当路由拥有子节点的时候会发生两件事

  1. 路由的url嵌套 ("/" + "expenses" and "/" + "invoices")
  2. 子路由组件匹配的时候也会渲染父组件共享的部分

接下来我们在App.jsx添加一个Outlet作为渲染子节点路由的地方

//src/App.jsx
import { Outlet, Link } from "react-router-dom";

export default function App() {
  return (
    

Bookkeeper

); }

这下我们就可以在两个路由间切换保持共享的布局了。

05.给Invoices路由添加数据

我们模拟真实使用场景,给Invoices路由造点假数据

// src/data.js
let invoices = [
  {
    name: "Santa Monica",
    number: 1995,
    amount: "$10,800",
    due: "12/05/1995"
  },
  {
    name: "Stankonia",
    number: 2000,
    amount: "$8,000",
    due: "10/31/2000"
  },
  {
    name: "Ocean Avenue",
    number: 2003,
    amount: "$9,500",
    due: "07/22/2003"
  },
  {
    name: "Tubthumper",
    number: 1997,
    amount: "$14,000",
    due: "09/01/1997"
  },
  {
    name: "Wide Open Spaces",
    number: 1998,
    amount: "$4,600",
    due: "01/27/2998"
  }
];

export function getInvoices() {
  return invoices;
}

然后我们修改invoices.jsx组件,获取并且渲染数据

//src/routes/invoices.jsx
import { Link } from "react-router-dom";
import { getInvoices } from "../data";

export default function Invoices() {
  let invoices = getInvoices();
  return (
    
); }

06.添加一个不匹配路由

我们可以发现,当我们输入一个没有分配地址的路由的时候,会显示空白页。

实际上有一个好办法就是把这些不匹配的路由都导入一个404页面。

我们添加一个"*"路由,这个路由会匹配所有没有匹配其他路由的路由

// src/index.js

  }>
    } />
    } />
    
          

There's nothing here!

} />

07.读取url参数

下面我们添加一些新组件,用于显示固定年份的invoice

// src/routes/invoice.jsx
export default function Invoice() {
  return 

Invoice #???

; }

然后我们在invoices路由下面添加这个子路由

// src/index.js

  }>
    } />
    }>
      } />
    
    
          

There's nothing here!

} />

我们刚刚创建的路由是匹配 "/invoices/2005" and "/invoices/1998"这种格式的。

然后我们还需要在invoices.jsx 添加一个outlet,不然显示不出来子路由的内容

然后我们在invoice.jsx 文件中获取url参数

// src/routes/invoice.jsx
import { useParams } from "react-router-dom";

export default function Invoice() {
  let params = useParams();
  return 

Invoice: {params.invoiceId}

; }

接着我们在data.js里面添加一个根据年份返回对应年份数据的函数

//...
export function getInvoices() {
  return invoices;
}

export function getInvoice(number) {
  return invoices.find(
    invoice => invoice.number === number
  );
}

然后我们就能用这个函数获取数据并且渲染出来了。

import { useParams } from "react-router-dom";
import { getInvoice } from "../data";

export default function Invoice() {
  let params = useParams();
  let invoice = getInvoice(parseInt(params.invoiceId, 10));
  return (
    

Total Due: {invoice.amount}

{invoice.name}: {invoice.number}

Due Date: {invoice.due}

); }

08.index路由

这可能是react router 里面最难理解的概念。

当我们浏览 invoices 路由的子路由内容,之后我们点击invoices路由的链接,我们发现右侧变成了空白。

我们可以添加一个index路由解决这个问题

// src/index.js


  }>
    } />
    }>
      
            

Select an invoice

} /> } />

There's nothing here!

} />

接下来我们发现点击invoices路由的时候会默认显示index路由的内容而不是空白。

index路由和其他路由不同的地方是它没有path属性,他和父路由共享同一个路径。

下面几点可以帮助你理解这个概念

  • index路由渲染在父路由的outlet,而且路由地址和父路由相同
  • index路由在父路由匹配并且其他子路由不匹配的时候 匹配
  • index路由是一个父节点默认的子节点
  • index路由在用户还没有点击导航中的链接时渲染

09.高亮激活的链接

通常我们需要,特别是在导航列表里面,需要展示给用户当前激活的链接是哪个。

西面我们把invoices.jsx中的Link换成NavLink

import { NavLink, Outlet } from "react-router-dom";
import { getInvoices } from "../data";

export default function Invoices() {
  let invoices = getInvoices();
  return (
    
); }

我们做了以下3件事

  1. 替换Link为NavLink

  2. 我们用函数改变样式

  3. 我们该百年了链接颜色通过NavLink传递过来的isActive属性

我们也可以利用className做到一样的效果。

// normal string


// function
 isActive ? "red" : "blue"} />

10.url搜索参数

搜索参数就类似于url参数,但是他们在url中所处的位置不同。

不是由/分隔,他们出现在一个?之后,类似于这样的形式 "/login?success=1"or"/shoes?brand=nike&sort=asc&sortby=price

react router 提供了 useSearchParams 用于读取和操作搜索参数。它有点像useState,不同点是useState是操作内存中的数据,

而他是设置url 搜索参数中的state

// routes/invoices.jsx
import {
  NavLink,
  Outlet,
  useSearchParams
} from "react-router-dom";
import { getInvoices } from "../data";

export default function Invoices() {
  let invoices = getInvoices();
  let [searchParams, setSearchParams] = useSearchParams();

  return (
    
); }

11.自定义行为

接着上一节的程序,

我们发现如果我们点击了过滤出来的链接,就不会保持过滤了,input会被清空。

我们能够在点击新链接的时候保持查询字符串,只要我们组合 Navlink和useLocation,组成一个我们自己的QueryNavLink

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

function QueryNavLink({ to, ...props }) {
  let location = useLocation();
  return ;
}

类似于 useSearchParams, useLocation 也会返回一个location告诉我们一些信息。就类似于下面的格式

{
  pathame: "/invoices",
  search: "?filter=sa",
  hash: "",
  state: null,
  key: "ae4cz2j"
}

12.编程式导航

有时我们需要更改URL,

我们添加一个按钮,将invoice删除,然后导航到索引路由。

首先我们在data.js里添加下面用于删除一个invoice的函数

export function deleteInvoice(number) {
  invoices = invoices.filter(
    invoice => invoice.number !== number
  );
}

然后我们添加删除按钮

// src/routes/invoice.jsx
import { useParams, useNavigate } from "react-router-dom";
import { getInvoice, deleteInvoice } from "../data";

export default function Invoice() {
  let navigate = useNavigate();
  let params = useParams();
  let invoice = getInvoice(parseInt(params.invoiceId, 10));

  return (
    

Total Due: {invoice.amount}

{invoice.name}: {invoice.number}

Due Date: {invoice.due}

); }

你可能感兴趣的:(2021 react-router v6 快速入门)