此篇章不會從頭開始介紹 React Router,而是挑選一些它的功能去做介紹,因此本篇的範例皆是從 React Router 官網找的範例。
React Router 實際上是由好幾個 package 組成,如圖所示:
首先第一個介紹的功能是巢狀路由,我們不只可以在最父層的元件建立 Router,也可以在子元件建立 Router,讓元件根據 Router 去做渲染。
可以看到 App 元件的子元件 Topics 也設定了 Router:
關於 useRouteMatch、useParams 等 hook 會在後面做介紹
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useRouteMatch,
useParams
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
</ul>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/topics">
<Topics />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
function Home() {
return <h2>Home</h2>;
}
function About() {
return <h2>About</h2>;
}
function Topics() {
let match = useRouteMatch();
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/components`}>Components</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Switch>
<Route path={`${match.path}/:topicId`}>
<Topic />
</Route>
<Route path={match.path}>
<h3>Please select a topic.</h3>
</Route>
</Switch>
</div>
);
}
function Topic() {
let { topicId } = useParams();
return <h3>Requested topic ID: {topicId}</h3>;
}
當某個頁面有表單並且使用者開始填寫但還未送出表單時,若使用者想連到其他畫面會跳出提醒,避免使用者誤觸連結跳轉到其他畫面。
import React, { useState } from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
Prompt
} from "react-router-dom";
export default function PreventingTransitionsExample() {
return (
<Router>
<ul>
<li>
<Link to="/">Form</Link>
</li>
<li>
<Link to="/one">One</Link>
</li>
<li>
<Link to="/two">Two</Link>
</li>
</ul>
<Switch>
<Route path="/" exact children={<BlockingForm />} />
<Route path="/one" children={<h3>One</h3>} />
<Route path="/two" children={<h3>Two</h3>} />
</Switch>
</Router>
);
}
function BlockingForm() {
let [isBlocking, setIsBlocking] = useState(false);
return (
<form
onSubmit={event => {
event.preventDefault();
event.target.reset();
setIsBlocking(false);
}}
>
<Prompt
when={isBlocking}
message={location =>
`Are you sure you want to go to ${location.pathname}`
}
/>
<p>
Blocking?{" "}
{isBlocking ? "Yes, click a link or the back button" : "Nope"}
</p>
<p>
<input
size="50"
placeholder="type something to block transitions"
onChange={event => {
setIsBlocking(event.target.value.length > 0);
}}
/>
</p>
<p>
<button>Submit to stop blocking</button>
</p>
</form>
);
}
React router 對帶有 Query Parameters 的 url 沒有限制,可以直接寫成路由。
另外也可以透過瀏覽器的 API "URLSearchParams" 去取出 query 值。
import React from "react";
import {
BrowserRouter as Router,
Link,
useLocation
} from "react-router-dom";
export default function QueryParamsExample() {
return (
<Router>
<QueryParamsDemo />
</Router>
);
}
function useQuery() {
return new URLSearchParams(useLocation().search);
}
function QueryParamsDemo() {
let query = useQuery();
return (
<div>
<div>
<h2>Accounts</h2>
<ul>
<li>
<Link to="/account?name=netflix">Netflix</Link>
</li>
<li>
<Link to="/account?name=zillow-group">Zillow Group</Link>
</li>
<li>
<Link to="/account?name=yahoo">Yahoo</Link>
</li>
<li>
<Link to="/account?name=modus-create">Modus Create</Link>
</li>
</ul>
<Child name={query.get("name")} />
</div>
</div>
);
}
function Child({ name }) {
return (
<div>
{name ? (
<h3>
The <code>name</code> in the query string is "{name}
"
</h3>
) : (
<h3>There is no name in the query string</h3>
)}
</div>
);
}
以上只是簡單介紹幾個功能,在閱讀完 React router 的官方文件後,覺得開發者將 React router 的各項功能、元件作用寫得相當清楚,也有附上 Demo 範例,除此之外也有分成 React 和 React native 兩種文件,可以點擊官方連結詳細閱讀囉!