使用 HTML5 的 history API (pushState, replaceState 和 popstate 事件) 来保持 UI 与 URL 同步的<router>
import { BrowserRouter } from 'react-router-dom'
<BrowserRouter
basename={optionalString}
forceRefresh={optionalBool}
getUserConfirmation={optionalFunc}
keyLength={optionalNumber}
>
<App />
</BrowserRouter>
/
开头,无需/
结尾<BrowserRouter basename="/calendar" />
<Link to="/today"/> <!-- renders <a href="/calendar/today"> -->
<BrowserRouter
getUserConfirmation={(message, callback) => {
// this is the default behavior
const allowTransition = window.confirm(message);
callback(allowTransition);
}}
/>
<BrowserRouter forceRefresh={true} />
<BrowserRouter keyLength={12} />
说明: 当 React 的版本 < 16 时, 必须使用单个子元素,因为 render 方法不能返回多个元素. 如果需要多个元素,可以尝试将它们包装在一个额外的 <div> 中
使用 URL 的 hash 部分 (即 window.location.hash) 来保持 UI 与 URL 同步的<router>
import { HashRouter } from 'react-router-dom'
<HashRouter
basename={optionalString}
getUserConfirmation={optionalFunc}
hashType={optionalString}
>
<App />
</HashRouter>
重要说明:<HashHistory> 不支持 location.key 或 location.state。在以前的版本中,我们试图填充行为,但有些边缘情况我们无法解决。任何需要此行为的代码或插件都无法工作。由于此技术仅用于支持传统浏览器,因此建议将服务器配置为使用 <BrowserHistory>。
/
开头,无需/
结尾<HashRouter basename="/calendar"/>
<Link to="/today"/> <!-- renders <a href="#/calendar/today"> -->
<HashRouter
getUserConfirmation={(message, callback) => {
// this is the default behavior
const allowTransition = window.confirm(message);
callback(allowTransition);
}}
/>
#/
和 #/sunshine/lollipops
的 hash#
和 #sunshine/lollipops
的 hash#!/
和#!/sunshine/lollipops
返回目录
将“url”的 history 保存在内存中的<router>(不读或写地址栏)。适用于测试和非浏览器环境,如 React Native。
import { MemoryRouter } from "react-router-dom";
<MemoryRouter
initialEntries={optionalArray}
initialIndex={optionalNumber}
getUserConfirmation={optionalFunc}
keyLength={optionalNumber}
>
<App />
</MemoryRouter>
<MemoryRouter
initialEntries={["/one", "/two", { pathname: "/three" }]}
initialIndex={1}
>
<App />
</MemoryRouter>
<MemoryRouter keyLength={12} />
The common low-level interface for all router components. Typically apps will use one of the high-level routers instead:
所有路由器组件的通用低级接口。通常,app将使用高级路由器之一:
The most common use-case for using the low-level is to synchronize a custom history with a state management lib like Redux or Mobx. Note that this is not required to use state management libs alongside React Router, it’s only for deep integration.
使用低级最常见的用例是将自定义历史与状态管理库(如redux或mobx)同步。请注意,在React路由器旁边使用状态管理libs不需要这样做,它只用于深度集成。
import React from "react";
import ReactDOM from "react-dom";
import { Router } from "react-router";
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
ReactDOM.render(
<Router history={history}>
<App />
</Router>,
node
);
import React from "react";
import ReactDOM from "react-dom";
import { createBrowserHistory } from "history";
const customHistory = createBrowserHistory();
ReactDOM.render(<Router history={customHistory} />, node);
<Router>
<App />
</Router>
A <Router> that never changes location.
This can be useful in server-side rendering scenarios when the user isn’t actually clicking around, so the location never actually changes. Hence, the name: static. It’s also useful in simple tests when you just need to plug in a location and make assertions on the render output.
这在服务器端渲染场景中非常有用,当用户没有实际单击时,这样位置就不会实际更改。因此,名称为:static。当您只需要插入一个位置并对渲染输出进行断言时,它在简单测试中也很有用
Here’s an example node server that sends a 302 status code for s and regular HTML for other requests:
下面是一个示例节点服务器,它为s发送302状态代码,为其他请求发送常规HTML:
import http from "http";
import React from "react";
import ReactDOMServer from "react-dom/server";
import { StaticRouter } from "react-router";
http
.createServer((req, res) => {
// This context object contains the results of the render
const context = {};
const html = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
// context.url will contain the URL to redirect to if a <Redirect> was used
if (context.url) {
res.writeHead(302, {
Location: context.url
});
res.end();
} else {
res.write(html);
res.end();
}
})
.listen(3000);
<StaticRouter basename="/calendar">
<Link to="/today"/> // renders <a href="/calendar/today">
</StaticRouter>
<StaticRouter location={req.url}>
<App />
</StaticRouter>
<StaticRouter location={{ pathname: "/bubblegum" }}>
<App />
</StaticRouter>
const context = {}
<StaticRouter context={context}>
<App />
</StaticRouter>
When a matches, it will pass the context object to the component it renders as the staticContext prop. Check out the Server Rendering guide for more information on how to do this yourself.
当一个匹配时,它将把上下文对象传递给它呈现为staticContext属性的组件。有关如何自己执行此操作的详细信息,请参阅《服务器呈现指南》。
After the render, these properties can be used to to configure the server’s response.
渲染之后,这些属性可用于配置服务器的响应。
if (context.status === "404") {
// ...
}
Note: On React < 16 you must use a single child element since a render method cannot return more than one element. If you need more than one element, you might try wrapping them in an extra <div>.
The Route component is perhaps the most important component in React Router to understand and learn to use well. Its most basic responsibility is to render some UI when its path matches the current URL.
路由组件可能是反应路由器中理解和学习良好使用的最重要组件。它最基本的职责是在位置与路由路径匹配时呈现一些UI。
Consider the following code:
考虑以下代码:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from 'react-router-dom'
ReactDOM.render(
<Router>
<div>
<Route exact path="/">
<Home />
</Route>
<Route path="/news">
<NewsFeed />
</Route>
</div>
</Router>,
node
);
If the location of the app is / then the UI hierarchy will be something like:
如果 app 的位置是 / 的话,那么UI层会有点像:
<div>
<Home/>
<!-- react-empty: 2 -->
</div>
And if the location of the app is /news then the UI hierarchy will be:
如果 app 的位置是 /news,那么UI层将会是:
<div>
<!-- react-empty: 1 -->
<NewsFeed/>
</div>
The “react-empty” comments are just implementation details of React’s null rendering. But for our purposes, it is instructive. A Route is always technically “rendered” even though its rendering null. When the 's path matches the current URL, it renders its children (your component).
“react empty” 注释只是 React 的空呈现的实现细节。但就我们的目的而言,这是有指导意义的。一个路由在技术上总是“渲染”,即使其渲染为空。一旦应用程序位置与路由路径匹配,就会呈现组件。
The recommended method of rendering something with a is to use children elements, as shown above. There are, however, a few other methods you can use to render something with a . These are provided mostly for supporting apps that were built with earlier versions of the router before hooks were introduced.
一个有三种方式来渲染:
You should use only one of these props on a given . See their explanations below to understand the differences between them.
旧–
Each is useful in different circumstances. You should use only one of these props on a given . See their explanations below to understand why you have 3 options. Most of the time you’ll use component.
每一种都在不同的情况下有用。在给定的<Route>上应该只使用其中一种属性。请参阅下面他们的解释,了解您为什么有3个选项。大多数情况下,您将使用component。
–
All three render methods will be passed the same three route props
所有的三种渲染方式将会接收到同样的三个路由参数
A React component to render only when the location matches. It will be rendered with route props.
仅当位置匹配时才渲染的 React 组件。它将使用路由参数渲染。
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";
// All route props (match, location and history) are available to User
function User(props) {
return <h1>Hello {props.match.params.username}!</h1>;
}
ReactDOM.render(
<Router>
<Route path="/user/:username" component={User} />
</Router>,
node
);
When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below).
当使用component(而不是下面的render或children)时,路由器使用react.createElement从给定组件创建新的react元素。这意味着,如果为组件属性提供内联函数,则每次渲染都将创建一个新组件。这将导致现有组件卸载和新组件安装,而不仅仅是更新现有组件。当使用内联函数进行内联渲染时,请使用render或children属性(如下)。
This allows for convenient inline rendering and wrapping without the undesired remounting explained above.
这样可以方便地进行内联渲染和包装,而无需上述不需要的重新安装。
Instead of having a new React element created for you using the component prop, you can pass in a function to be called when the location matches. The render prop function has access to all the same route props (match, location and history) as the component render prop.
不必使用component为您创建新的react元素,您可以传入一个函数,当位置匹配时调用该函数。render参数函数可以访问与component的渲染参数相同的所有路由参数(match, location 和 history)。
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";
// convenient inline rendering
ReactDOM.render(
<Router>
<Route path="/home" render={() => <div>Home</div>} />
</Router>,
node
);
// wrapping/composing
// You can spread routeProps to make them available to your rendered Component
function FadingRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={routeProps => (
<FadeIn>
<Component {...routeProps} />
</FadeIn>
)}
/>
);
}
ReactDOM.render(
<Router>
<FadingRoute path="/cool" component={Something} />
</Router>,
node
);
Warning: <Route component> takes precedence over <Route render> so don’t use both in the same <Route>.
警告:<Route component>优先于<Route render>,因此不要在同一<Route>中同时使用这两者。
Sometimes you need to render whether the path matches the location or not. In these cases, you can use the function children prop. It works exactly like render except that it gets called whether there is a match or not.
有时需要渲染路径是否与位置匹配。在这些情况下,您可以使用函数children 属性。它的工作原理与render完全相同,只是不管是否匹配都会调用它。
The children render prop receives all the same route props as the component and render methods, except when a route fails to match the URL, then match is null. This allows you to dynamically adjust your UI based on whether or not the route matches. Here we’re adding an active class if the route matches
子级渲染属性接收与组件和渲染方法相同的所有路由属性,除非路由与URL不匹配,否则匹配为空。这允许您根据路由是否匹配来动态调整UI。这里,如果路由匹配,我们将添加一个活动类
import React from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Link,
Route
} from "react-router-dom";
function ListItemLink({ to, ...rest }) {
return (
<Route
path={to}
children={({ match }) => (
<li className={match ? "active" : ""}>
<Link to={to} {...rest} />
</li>
)}
/>
);
}
ReactDOM.render(
<Router>
<ul>
<ListItemLink to="/somewhere" />
<ListItemLink to="/somewhere-else" />
</ul>
</Router>,
node
);
This could also be useful for animations:
这也适用于animations
<Route
children={({ match, ...rest }) => (
{/* Animate will always render, so you can use lifecycles
to animate its child in and out */}
<Animate>
{match && <Something {...rest}/>}
</Animate>
)}
/>
新
Warning: <Route children> takes precedence over both <Route component> and <Route render> so don’t use more than one in the same .
旧
Warning: Both <Route component> and <Route render> take precedence over <Route children> so don’t use more than one in the same .
警告:<Route component>和<Route render>都优先于<Route children>,因此不要在同一中使用多个。
<Route path="/users/:id">
<User />
</Route>
<Route path={["/users/:id", "/profile/:id"]}>
<User />
</Route>
Routes without a path always match.
没有路径的路由总是匹配的。
<Route exact path="/one">
<About />
</Route>
path | location.pathname | exact | matches? |
---|---|---|---|
/one | /one/two | true | no |
/one | /one/two | false | yes |
<Route strict path="/one/">
<About />
</Route>
path | location.pathname | matches? |
---|---|---|
/one/ | /one | no |
/one/ | /one/ | yes |
/one/ | /one/two | yes |
Warning: strict can be used to enforce that a location.pathname has no trailing slash, but in order to do this both strict and exact must be true.
警告:Strict可用于强制location.pathname没有尾随斜杠,但要执行此操作,Strict和Exact都必须为true。
<Route exact strict path="/one">
<About />
</Route>
path | location.pathname | matches? |
---|---|---|
/one | /one | yes |
/one | /one/ | no |
/one | /one/two | no |
A <Route> element tries to match its path to the current history location (usually the current browser URL). However, a location with a different pathname can also be passed for matching.
元素尝试将其路径与当前历史记录位置(通常是当前浏览器URL)匹配。但是,也可以传递具有不同路径名的位置进行匹配。
This is useful in cases when you need to match a <Route> to a location other than the current history location, as shown in the Animated Transitions example.
这在需要将<Route>匹配到当前历史位置以外的位置时非常有用,如动画转换示例中所示。
If a <Route> element is wrapped in a <Switch> and matches the location passed to the <Switch> (or the current history location), then the location prop passed to <Route> will be overridden by the one used by the <Switch> (given here).
如果一个<Route>元素包装在一个<Switch>中,并且与传递给<Switch>的位置(或当前历史位置)匹配,那么传递给<Route>的位置属性将被<Switch>使用的属性覆盖(此处给出)。
<Route sensitive path="/one">
<About />
</Route>
path | location.pathname | sensitive | matches? |
---|---|---|---|
/one | /one | true | yes |
/One | /one | true | no |
/One | /one | false | yes |
Renders the first child <Route> or <Redirect> that matches the location.
渲染 第一个与位置匹配的子级<Route>或<Redirect>。
How is this different than just using a bunch of <Route>s?
这与使用一组有什么不同?
<Switch> is unique in that it renders a route exclusively. In contrast, every <Route> that matches the location renders inclusively. Consider this code:
<Switch>是唯一的,因为它只渲染路由。与此相反,与位置匹配的每个<Route>都包含在内。考虑此代码:
import { Route } from "react-router";
let routes = (
<div>
<Route path="/about">
<About />
</Route>
<Route path="/:user">
<User />
</Route>
<Route>
<NoMatch />
</Route>
</div>
);
If the URL is /about, then , , and will all render because they all match the path. This is by design, allowing us to compose s into our apps in many ways, like sidebars and breadcrumbs, bootstrap tabs, etc.
如果URL是/about,则、和将全部渲染,因为它们都与路径匹配。这是通过设计实现的,允许我们以多种方式将组合到应用程序中,比如侧边栏和面包屑导航、引导选项卡等。
Occasionally, however, we want to pick only one to render. If we’re at /about we don’t want to also match /:user (or show our “404” page). Here’s how to do it with Switch:
但是,有时我们只想选择一个进行渲染。如果我们在/about 我们不想也匹配/:user(或显示我们的“404”页)。下面介绍如何使用Switch:
import { Route, Switch } from "react-router";
let routes = (
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/:user">
<User />
</Route>
<Route>
<NoMatch />
</Route>
</Switch>
);
Now, if we’re at /about, <Switch> will start looking for a matching <Route>. <Route path="/about"/> will match and <Switch> will stop looking for matches and render <About>. Similarly, if we’re at /michael then <User> will render.
现在,如果我们是/about,
This is also useful for animated transitions since the matched <Route> is rendered in the same position as the previous one.
这对于动画转换也很有用,因为匹配的<Route>与前一个位置渲染在同一位置。
let routes = (
<Fade>
<Switch>
{/* there will only ever be one child here */}
<Route />
<Route />
</Switch>
</Fade>
);
let routes = (
<Fade>
{/* there will always be two children here,
one might render null though, making transitions
a bit more cumbersome to work out */}
<Route />
<Route />
</Fade>
);
All children of a <Switch> should be <Route> or <Redirect> elements. Only the first child to match the current location will be rendered.
<Switch>的所有子元素都应该是<Route>或<Redirect>元素。将只呈现与当前位置匹配的第一个子级。
<Route> elements are matched using their path prop and <Redirect> elements are matched using their from prop. A <Route> with no path prop or a <Redirect> with no from prop will always match the current location.
<Route>元素使用其路径属性匹配,而<Redirect>元素使用其from属性匹配。没有路径道具的\或没有from道具的<Redirect>将始终匹配当前位置。
When you include a <Redirect> in a <Switch>, it can use any of the <Route>'s location matching props: path, exact, and strict. from is just an alias for the path prop.
当您在<Switch>中包含<Redirect>时,它可以使用任何<Route>的位置匹配属性:path、exact和strict。from只是路径属性的别名。
If a location prop is given to the <Switch>, it will override the location prop on the matching child element.
如果为<Switch>提供了location属性,它将覆盖匹配子元素上的location属性。
import { Redirect, Route, Switch } from "react-router";
let routes = (
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/users">
<Users />
</Route>
<Redirect from="/accounts" to="/users" />
<Route>
<NoMatch />
</Route>
</Switch>
);
Rendering a <Redirect> will navigate to a new location. The new location will override the current location in the history stack, like server-side redirects (HTTP 3xx) do.
渲染 <Redirect> 将 navigate 到新 location。新位置将覆盖历史堆栈中的当前位置,如服务器端重定向(HTTP 3xx)所做的操作。
<Route exact path="/">
{loggedIn ? <Redirect to="/dashboard" /> : <PublicHomePage />}
</Route>
<Redirect to="/somewhere/else" />
<Redirect
to={{
pathname: "/login",
search: "?utm=your+face",
state: { referrer: currentLocation }
}}
/>
The state object can be accessed via this.props.location.state in the redirected-to component. This new referrer key (which is not a special name) would then be accessed via this.props.location.state.referrer in the Login component pointed to by the pathname ‘/login’
可以通过重定向到组件中的this.props.location.state访问state对象。然后,可以通过路径名“/login”指向的登录组件中的this.props.location.state.referer访问此新的referer密钥(不是特殊名称)。
<Redirect push to="/somewhere/else" />
<Switch>
<Redirect from='/old-path' to='/new-path' />
<Route path='/new-path'>
<Place />
</Route>
</Switch>
// Redirect with matched parameters
<Switch>
<Redirect from='/users/:id' to='/users/profile/:id'/>
<Route path='/users/profile/:id'>
<Profile />
</Route>
</Switch>
<Switch>
<Redirect exact from="/" to="/home" />
<Route path="/home">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
</Switch>
<Switch>
<Redirect strict from="/one/" to="/home" />
<Route path="/home">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
</Switch>
返回目录
为应用提供声明、可访问的跳转链接(navigate)。
import { Link } from 'react-router-dom'
<Link to="/about">About</Link>
<Link to="/courses?sort=name" />
<Link
to={{
pathname: "/courses",
search: "?sort=name",
hash: "#the-hash",
state: { fromDashboard: true }
}}
/>
<Link to={location => ({ ...location, pathname: "/courses" })} />
<Link to={location => `${location.pathname}?sort=name`} />
<Link to="/courses" replace />
返回目录
一个特殊版本的 Link,当它匹配当前URL时,会在元素上增加样式相关的属性(从而达到高亮标记的效果)
import { NavLink } from 'react-router-dom'
<NavLink to="/about">About</NavLink>
类型:string
说明:当元素处于活动状态时提供该元素的类。默认的给定类是活动的。这将与classname属性结合在一起。
The class to give the element when it is active. The default given class is active. This will be joined with the className prop.
<NavLink to="/faq" activeClassName="selected">
FAQs
</NavLink>
<NavLink
to="/faq"
activeStyle={{
fontWeight: "bold",
color: "red"
}}
>
FAQs
</NavLink>
<NavLink exact to="/profile">
Profile
</NavLink>
<NavLink strict to="/events/">
Events
</NavLink>
<NavLink
to="/events/123"
isActive={(match, location) => {
if (!match) {
return false;
}
// only consider an event active if its event id is an odd number
const eventID = parseInt(match.params.eventID);
return !isNaN(eventID) && eventID % 2 === 1;
}}
>
Event 123
</NavLink>
The value of the aria-current attribute used on an active link. Available values are:
用于在离开页面前提示用户。当应用程序进入一个应该阻止用户跳转的状态时(就像一个表单被填了一半),请呈现一个。
import { Prompt } from 'react-router'
<Prompt
when={formIsHalfFilledOut}
message="Are you sure you want to leave?"
/>
<Prompt when={formIsHalfFilledOut} message="Are you sure?" />
<Prompt
message={location =>
location.pathname.startsWith("/app")
? true
: `Are you sure you want to go to ${location.pathname}?`
}
/>
<Prompt when={formIsHalfFilledOut} message="Are you sure?" />
The term “history” and “history object” in this documentation refers to the history package, which is one of only 2 major dependencies of React Router (besides React itself), and which provides several different implementations for managing session history in JavaScript in various environments.
本文档中的术语“history”和“history object”是指history包,它是React Router (除了React本身)仅有的两个主要依赖项之一,它提供了几种不同的实现,用于在不同环境中管理javascript中的会话历史。
The following terms are also used:
还使用以下术语:
history objects typically have the following properties and methods:
history对象通常具有以下属性和方法:
The history object is mutable. Therefore it is recommended to access the location from the render props of <Route>, not from history.location. This ensures your assumptions about React are correct in lifecycle hooks. For example:
history对象是可变的。因此,建议从<Route>的渲染属性访问位置,而不是从history.location。这可以确保您对React的假设在生命周期钩子中是正确的。例如:
class Comp extends React.Component {
componentDidUpdate(prevProps) {
// will be true
const locationChanged =
this.props.location !== prevProps.location;
// INCORRECT, will *always* be false because history is mutable.
const locationChanged =
this.props.history.location !== prevProps.history.location;
}
}
<Route component={Comp} />;
Additional properties may also be present depending on the implementation you’re using. Please refer to the history documentation for more details.
根据您使用的实现,还可能存在其他属性。有关详细信息,请参阅history文档。
Locations represent where the app is now, where you want it to go, or even where it was. It looks like this:
location代表app的现在位置,你想要它去的地方,甚至是它原来的位置。看起来是这样的:
{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere'
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}
The router will provide you with a location object in a few places:
路由器将在几个地方为您提供一个位置对象:
It is also found on history.location but you shouldn’t use that because its mutable. You can read more about that in the history doc.
它也可以在history.location上找到,但您不应该使用它,因为它是可变的。你可以在历史文件中了解更多。
A location object is never mutated so you can use it in the lifecycle hooks to determine when navigation happens, this is really useful for data fetching and animation.
location对象永远不会发生变化,因此您可以在生命周期钩子中使用它来确定何时进行导航,这对于数据获取和动画非常有用。
componentWillReceiveProps(nextProps) {
if (nextProps.location !== this.props.location) {
// navigated!
}
}
You can provide locations instead of strings to the various places that navigate:
您可以为导航的各个位置提供位置而不是字符串:
Normally you just use a string, but if you need to add some “location state” that will be available whenever the app returns to that specific location, you can use a location object instead. This is useful if you want to branch UI based on navigation history instead of just paths (like modals).
通常,您只需要使用一个字符串,但是如果您需要添加一些“位置状态”,当应用程序返回到特定位置时,它将可用,您可以使用一个位置对象。如果您希望基于导航历史而不仅仅是路径(如模态)来分支UI,那么这非常有用。
// usually all you need
<Link to="/somewhere"/>
// but you can use a location instead
const location = {
pathname: '/somewhere',
state: { fromDashboard: true }
}
<Link to={location}/>
<Redirect to={location}/>
history.push(location)
history.replace(location)
Finally, you can pass a location to the following components:
最后,可以将位置传递给以下组件:
This will prevent them from using the actual location in the router’s state. This is useful for animation and pending navigation, or any time you want to trick a component into rendering at a different location than the real one.
这将阻止他们使用路由器状态下的实际位置。这对于动画和挂起的导航很有用,或者在任何时候您想要欺骗一个组件,使其在与真实组件不同的位置进行渲染。
A match object contains information about how a <Route path> matched the URL. match objects contain the following properties:
match对象包含有关如何匹配URL的信息。match对象包含以下属性:
You’ll have access to match objects in various places:
您可以在不同位置访问match对象
If a Route does not have a path, and therefore always matches, you’ll get the closest parent match. Same goes for withRouter.
如果路由没有路径,因此始终匹配,则会得到最近的父匹配。withRouter也是如此。
A <Route> that uses the children prop will call its children function even when the route’s path does not match the current location. When this is the case, the match will be null. Being able to render a <Route>'s contents when it does match can be useful, but certain challenges arise from this situation.
即使路由的路径与当前位置不匹配,使用子属性的<Route>也将调用其children函数。在这种情况下,match将为空。当匹配时能够渲染<Route>的内容是有用的,但是这种情况会带来一些挑战。
The default way to “resolve” URLs is to join the match.url string to the “relative” path.
“解析”URL的默认方法是将match.url字符串连接到“relative”路径
let path = `${match.url}/relative-path`;
If you attempt to do this when the match is null, you will end up with a TypeError. This means that it is considered unsafe to attempt to join “relative” paths inside of a <Route> when using the children prop.
如果在match为空时尝试执行此操作,则将以类型错误结束。这意味着当使用children prop时,尝试连接<Route>内的“相对”路径是不安全的。
A similar, but more subtle situation occurs when you use a pathless <Route> inside of a <Route> that generates a null match object.
当在生成空match对象的<Route>内部使用无路径的<Route>时,会出现类似但更微妙的情况。
// location.pathname = '/matches'
<Route path='/does-not-match' children={({ match }) => (
// match === null
<Route render={({ match:pathlessMatch }) => (
// pathlessMatch === ???
)}/>
)}/>
Pathless <Route>s inherit their match object from their parent. If their parent match is null, then their match will also be null. This means that a) any child routes/links will have to be absolute because there is no parent to resolve with and b) a pathless route whose parent match can be null will need to use the children prop to render.
无路径的<Route>s从其父对象继承其match对象。如果他们的父match为空,那么他们的match也将为空。这意味着a)任何routes/links都必须是绝对的,因为没有要解析的父路由;b)父match可以为空的无路径路由需要使用children属性进行渲染。
This lets you use the same matching code that <Route> uses except outside of the normal render cycle, like gathering up data dependencies before rendering on the server.
这允许您使用与<Route>使用的相同的匹配代码,除了正常渲染周期之外,例如在服务器上渲染之前收集数据依赖项。
import { matchPath } from "react-router";
const match = matchPath("/users/123", {
path: "/users/:id",
exact: true,
strict: false
});
The first argument is the pathname you want to match. If you’re using this on the server with Node.js, it would be req.path.
第一个参数是要匹配的路径名。如果您在node.js服务器上使用它,它将是req.path
The second argument are the props to match against, they are identical to the matching props Route accepts:
第二个参数是要匹配的属性,它们与匹配的属性路由接受的属性相同:
{
path, // like /users/:id; either a single string or an array of strings
strict, // optional, defaults to false
exact, // optional, defaults to false
}
It returns an object when provided pathname does match path prop.
如果提供的路径名与路径属性不匹配,则返回对象,否则返回空值
matchPath("/users/2", {
path: "/users/:id",
exact: true,
strict: true
});
// {
// isExact: true
// params: {
// id: "2"
// }
// path: "/users/:id"
// url: "/users/2"
// }
It returns null when provided pathname does not match path prop.
matchPath("/users", {
path: "/users/:id",
exact: true,
strict: true
});
// null
You can get access to the history object’s properties and the closest <Route>'s match via the withRouter higher-order component. withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
你可以通过 withRouter 高阶组件 访问 history 对象的属性和最近的<Route>的match。withrouter将在每次render时将更新的match、location和history属性传递给包装的组件。
import React from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
render() {
const { match, location, history } = this.props;
return <div>You are now at {location.pathname}</div>;
}
}
// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation);
Important Note
重要提示
withRouter does not subscribe to location changes like React Redux’s connect does for state changes. Instead, re-renders after location changes propagate out from the <Router> component. This means that withRouter does not re-render on route transitions unless its parent component re-renders.
WithRouter不订阅location更改,就像React Redux的Connect订阅state更改一样。相反,在location更改从<Router>组件传播出去之后重新渲染。这意味着withrouter不会在路由转换时重新渲染,除非其父组件重新渲染。
Static Methods and Properties
静态方法和属性
All non-react specific static methods and properties of the wrapped component are automatically copied to the “connected” component.
封装组件的所有非React特定静态方法和属性都会自动复制到“已连接”组件。
The wrapped component is exposed as the static property WrappedComponent on the returned component, which can be used for testing the component in isolation, among other things.
被包装的组件暴露为返回组件上的静态属性WrappedComponent ,该组件可用于隔离测试组件等。
// MyComponent.js
export default withRouter(MyComponent)
// MyComponent.test.js
import MyComponent from './MyComponent'
render(<MyComponent.WrappedComponent location={{...}} ... />)
A function that will be passed as the ref prop to the wrapped component.
将作为ref属性传递给包装组件的函数。
class Container extends React.Component {
componentDidMount() {
this.component.doSomething();
}
render() {
return <MyComponent wrappedComponentRef={c => (this.component = c)} />;
}
}
React Router ships with a few hooks that let you access the state of the router and perform navigation from inside your components.
Please note: You need to be using React >= 16.8 in order to use any of these hooks!
The useHistory hook gives you access to the history instance that you may use to navigate.
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
The useLocation hook returns the location object that represents the current URL. You can think about it like a useState that returns a new location whenever the URL changes.
This could be really useful e.g. in a situation where you would like to trigger a new “page view” event using your web analytics tool whenever a new page loads, as in the following example:
import React from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Switch,
useLocation
} from "react-router-dom";
function usePageViews() {
let location = useLocation();
React.useEffect(() => {
ga.send(["pageview", location.pathname]);
}, [location]);
}
function App() {
usePageViews();
return <Switch>...</Switch>;
}
ReactDOM.render(
<Router>
<App />
</Router>,
node
);
useParams returns an object of key/value pairs of URL parameters. Use it to access match.params of the current <Route>.
import React from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Switch,
Route,
useParams
} from "react-router-dom";
function BlogPost() {
let { slug } = useParams();
return <div>Now showing post {slug}</div>;
}
ReactDOM.render(
<Router>
<Switch>
<Route exact path="/">
<HomePage />
</Route>
<Route path="/blog/:slug">
<BlogPost />
</Route>
</Switch>
</Router>,
node
);
The useRouteMatch hook attempts to match the current URL in the same way that a <Route> would. It’s mostly useful for getting access to the match data without actually rendering a <Route>.
Now, instead of
import { Route } from "react-router-dom";
function BlogPost() {
return (
<Route
path="/blog/:slug"
render={({ match }) => {
// Do whatever you want with the match...
return <div />;
}}
/>
);
}
you can just
import { useRouteMatch } from "react-router-dom";
function BlogPost() {
let match = useRouteMatch("/blog/:slug");
// Do whatever you want with the match...
return <div />;
}