React Router v6 初探

在这篇文章写作时,React Router v6仍然处于alpha状态,但现在是时候开始玩它并探索即将到来的内容了。

正如你可能知道的,主要维护者在2018年初创建了React Router(LINK0)项目,以创建一个名为Reach Router(LINK1)的轻量级替代方案。

在此期间,这两个库都增长了,但似乎Reach Router的活跃开发将停止,并将合并到 即将到来的React Router v6

随着发布即将到来,这里是即将到来的东西的尖锐观点!

跳到...

正在变成

这个顶级组件将被更名,但其功能大多保持不变。

 1// v5
 2import {
 3  BrowserRouter,
 4  Switch,
 5  Route
 6} from 'react-router-dom';
 7
 8function App() {
 9  return (
10    <BrowserRouter>
11      <Switch>
12        <Route exact path="/"><Home /></Route>
13        <Route path="/profile"><Profile /></Route>
14      </Switch>
15    </BrowserRouter>
16  );
17}

只需点击路线:

 1// v6
 2import {
 3  BrowserRouter,
 4  Routes,
 5  Route
 6} from 'react-router-dom';
 7
 8function App() {
 9  return (
10    <BrowserRouter>
11      <Routes>
12        <Route path="/" element={<Home />} />
13        <Route path="profile/*" element={<Profile />} />
14      </Routes>
15    </BrowserRouter>
16  );
17}

巨大的变化与路线

在 v6 中, 组件正在接受最大的翻新,幸运的是,这些新变化实际上将使其更易于使用!

组件/返回器替换为元素:

 1import Profile from './Profile';
 2
 3// v5
 4<Route path=":userId" component={Profile} />
 5<Route
 6  path=":userId"
 7  render={routeProps => (
 8    <Profile routeProps={routeProps} animate={true} />
 9  )}
10/>
11
12// v6
13<Route path=":userId" element={<Profile />} />
14<Route path=":userId" element={<Profile animate={true} />} />

如果你注意到,在v6中,现在通过补丁更容易,这已经否定了v5中的渲染补丁的使用。

网游路线更简单

v5中的嵌套路径必须非常明确地定义,这需要将大量的符串匹配逻辑纳入这些组件中。

 1// v5
 2import {
 3  BrowserRouter,
 4  Switch,
 5  Route,
 6  Link,
 7  useRouteMatch
 8} from 'react-router-dom';
 9
10function App() {
11  return (
12    <BrowserRouter>
13      <Switch>
14        <Route exact path="/" component={Home} />
15        <Route path="/profile" component={Profile} />
16      </Switch>
17    </BrowserRouter>
18  );
19}
20
21function Profile() {
22
23  let match = useRouteMatch();
24
25  return (
26    <div>
27      <nav>
28        <Link to={`${match.url}/me`}>My Profile</Link>
29      </nav>
30
31      <Switch>
32        <Route path={`${match.path}/me`}>
33          <MyProfile />
34        </Route>
35        <Route path={`${match.path}/:id`}>
36          <OthersProfile />
37        </Route>
38      </Switch>
39    </div>
40  );
41}

在 v6 中,你可以删除符串匹配逻辑. 也不需要使用 useRouteMatch()! 结果很小:

 1// v6
 2import {
 3  BrowserRouter,
 4  Routes,
 5  Route,
 6  Link,
 7  Outlet
 8} from 'react-router-dom';
 9
10// Approach #1
11function App() {
12  return (
13    <BrowserRouter>
14      <Routes>
15        <Route path="/" element={<Home />} />
16        <Route path="profile/*" element={<Profile/>} />
17      </Routes>
18    </BrowserRouter>
19  );
20}
21
22function Profile() {
23  return (
24    <div>
25      <nav>
26        <Link to="me">My Profile</Link>
27      </nav>
28
29      <Routes>
30        <Route path="me" element={<MyProfile />} />
31        <Route path=":id" element={<OthersProfile />} />
32      </Routes>
33    </div>
34  );
35}
36
37// Approach #2
38// You can also define all
39// <Route> in a single place
40function App() {
41  return (
42    <BrowserRouter>
43      <Routes>
44        <Route path="/" element={<Home />} />
45        <Route path="profile" element={<Profile />}>
46          <Route path=":id" element={<MyProfile />} />
47          <Route path="me" element={<OthersProfile />} />
48        </Route>
49      </Routes>
50    </BrowserRouter>
51  );
52}
53
54function Profile() {
55  return (
56    <div>
57      <nav>
58        <Link to="me">My Profile</Link>
59      </nav>
60
61      <Outlet />
62    </div>
63  )
64}

注意: 组件在 React Router v6 中被用作{this.props.children}

使用代替使用历史

例如,在用户提交表单后,他们需要被重定向到确认页面,这是 v5 中的useHistory库,在 v6 被更名为useNavigate:

 1// v5
 2import { useHistory } from 'react-router-dom';
 3
 4function MyButton() {
 5  let history = useHistory();
 6  function handleClick() {
 7    history.push('/home');
 8  };
 9  return <button onClick={handleClick}>Submit</button>;
10};

现在 history.push() 将取代 navigate():

 1// v6
 2import { useNavigate } from 'react-router-dom';
 3
 4function MyButton() {
 5  let navigate = useNavigate();
 6  function handleClick() {
 7    navigate('/home');
 8  };
 9  return <button onClick={handleClick}>Submit</button>;
10};

在某些情况下,你会希望在浏览器历史中更换一个URL,而不是推一个新的URL。

1// v5
2history.push('/home');
3history.replace('/home');
4
5// v6
6navigate('/home');
7navigate('/home', {replace: true});

从 20KB 到 8KB

有了所有这些变化,你会期望包的大小会增加,但实际上它减少了一半! v5 的缩小包是 ~20kb,而 v6 只是 ~8kb。

Screenshot: React router v5 vs v6

使用 BundlePhobia工具计算包尺寸。

结论

我对React Router v6的发布感到非常兴奋,希望这篇文章给了你一个想法,当它发布时(这应该很快!)你可以阅读更多关于React Router v6的最新版本注释(https://github.com/ReactTraining/react-router/releases/tag/v6.0.0-alpha.2)

<$>[注] 新功能的完整列表,请参阅官方 React Router v6 迁移指南 <$>

Published At
Categories with 技术
Tagged with
comments powered by Disqus