API
Hooks(钩子)
useHistory
该useHistory
钩子,可以进行路由导航。
// useHistory
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Link, Route, Switch, useHistory, withRouter } from 'react-router-dom';
const Home = () => {
return <div>Home</div>;
};
const About = () => {
const history = useHistory();
const handleClick = () => {
console.log(useHistory);
history.push('/');
};
return (
<>
<div>About</div>
<button type="button" onClick={handleClick}>
Go home
</button>
</>
);
};
const TestHomeButton = () => {
const history = useHistory();
const errClick = () => {
console.log(useHistory);
history.push('/');
};
return (
<>
<BrowserRouter>
<button type="button" onClick={errClick}>
Go home(错误方式)
</button>
<h1>App</h1>
<ul>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/">home</Link>
</li>
</ul>
<Switch>
<Route exact={true} path="/" component={Home} />
<Route exact={true} path="/about" component={About} />
</Switch>
</BrowserRouter>
</>
);
};
ReactDOM.render(<TestHomeButton />, document.body);
注意useHistory使用的条件,使用不当会报错 ' Cannot read property 'push' of undefined',原因: 您正试图在
Router
之外使用history
钩子。在对应
组件中编写函数。
useLocation
该useLocation
钩子返回location
表示当前URL对象。您可以将其视为一个useState,每当URL更改时,它都会返回一个URL对象.
这可能非常有用,例如在您希望在加载新页面时监视location变化做点事情,如下例所示:
// useLocation
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Link, Route, Switch, useLocation } from 'react-router-dom';
const Home = () => {
let location = useLocation();
React.useEffect(() => {
console.log(location);
// alert('做自己喜欢的事情');
}, [location]);
return <div>home</div>;
};
const App = () => {
return (
<>
<BrowserRouter>
<h1>App</h1>
<ul>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/">home</Link>
</li>
</ul>
<Switch>
<Route exact={true} path="/" component={Home} />
<Route exact={true} path="/about" render={() => <div>about</div>} />
</Switch>
</BrowserRouter>
</>
);
};
ReactDOM.render(<App />, document.body);
location
:
{
hash: '',
key: 'y01zme',
pathname: '/',
search: '',
state: undefined,
}
注意需要在Router之内使用,要不然报错。
useParams
useParams
返回 URL 参数的键/值对对象。使用它来获取<Route>
参数.
// useParams
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Link, Route, Switch, useParams } from 'react-router-dom';
const About = () => {
let params = useParams();
return <div>useParams: {JSON.stringify(params)}</div>;
};
const App = () => {
return (
<>
<BrowserRouter>
<h1>App</h1>
<ul>
<li>
<Link to="/about/xxxx">About</Link>
</li>
<li>
<Link to="/">home</Link>
</li>
</ul>
<Switch>
<Route exact={true} path="/" render={() => <div>home</div>} />
<Route exact={true} path="/about/:slug" component={About} />
</Switch>
</BrowserRouter>
</>
);
};
ReactDOM.render(<App />, document.body);
对象key 取决于path参数/:slug的slug
useRouteMatch
useRouteMatch
挂钩尝试以与<Route>
相同的方式匹配当前URL
。在无需实际呈现<Route>
的情况下访问匹配数据最有用.\
不带参数时候,返回<Route>
的match
对象。
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Link, Route, Switch, useRouteMatch } from 'react-router-dom';
const About = () => {
let match = useRouteMatch();
return <div>useRouteMatch: {JSON.stringify(match)}</div>;
};
const App = () => {
return (
<>
<BrowserRouter>
<h1>App</h1>
<ul>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/">home</Link>
</li>
</ul>
<Switch>
<Route exact={true} path="/" render={() => <div>home</div>} />
<Route exact={true} path="/about" component={About} />
</Switch>
</BrowserRouter>
</>
);
};
ReactDOM.render(<App />, document.body);
match:
{
"path":"/about",
"url":"/about",
"isExact":true, // 是否匹配
"params":{}
}
接受参数时候,参数与match的props参数相同,它可以是字符串的路径名,也可以是带有组件的route对象
const match = useRouteMatch({
path: "/BLOG/:slug/",
strict: true,
sensitive: true
});
BrowserRouter
使用HTML5historyAPI(pushState、replaceState和popstate事件)保持UI与URL同步的。
basename
路由前缀,格式正确的basename应该有一个前导斜杠,但没有尾随斜杠。
<BrowserRouter basename="/calendar">
<Link to="/today"/> // renders <a href="/calendar/today">
<Link to="/tomorrow"/> // renders <a href="/calendar/tomorrow">
...
</BrowserRouter>
getUserConfirmation
用于确认导航的功能。默认使用window.confirm
。
<BrowserRouter
getUserConfirmation={(message, callback) => {
// 这是默认行为
const allowTransition = window.confirm(message);
callback(allowTransition);
}}
/>
hashType
用于 window.location.hash
的编码类型。可用值为:
"slash"
- Creates hashes like#/
and#/sunshine/lollipops
"noslash"
- Creates hashes like#
and#sunshine/lollipops
"hashbang"
- Creates “ajax crawlable” (deprecated by Google) hashes like#!/
and#!/sunshine/lollipops
默认 slash
children
要渲染的单个子元素。
link
在应用程序周围提供声明性的、可访问的导航。
to: string
链接位置的字符串表示形式,通过url、search和hash属性渲染对应router。
<Link to="/about">About</Link>
<Link to="/courses?sort=name" />
to: string
可以具有以下任何属性的对象:
pathname
: 表示要链接到的路径的字符串。search
: 查询参数的字符串表示形式。hash
: 查询参数的字符串表示形式。放在URL中的哈希,例如“A-hash”。state
: 要传输状态数据。
<Link
to={{
pathname: "/courses",
search: "?sort=name",
hash: "#the-hash",
state: { fromDashboard: true }
}}
/>
to: function
接收“location”的状态。作为参数传递给该函数,该函数应将返回to的对象或字符串路径。
<Link to={location => ({ ...location, pathname: "/courses" })} />
<Link to={location => `${location.pathname}?sort=name`} />
replace: boolean
如果为true,单击链接将替换历史堆栈中的当前条目,而不是添加新条目。
<Link to="/courses" replace />
innerRef: function
从React路由器5.1开始,如果您使用的是React 16,则不需要此api,因为我们将ref转发到基础a。改用普通的ref。
<Link
to="/"
innerRef={node => {
// `node`指挂载的DOM元素
// or null when unmounted
}}
/>
innerRef: RefObject
如果您使用的是React 16,则不需要此api 使用React.createRef获取组件的底层ref;
let anchorRef = React.createRef()
<Link to="/" innerRef={anchorRef} />
在React 16 以上, 中直接使用ref
let anchorRef = React.createRef()
<Link to="/" ref={anchorRef} />
component: React.Component
如果您想使用自己的导航组件,只需通过组件api传递它即可。
const FancyLink = React.forwardRef((props, ref) => (
<a ref={ref} {...props}>💅 {props.children}</a>
))
<Link to="/" component={FancyLink} />
others
您还可以传递在上使用的属性,如标题、id、类名等。
NavLink
<Link>
的一个特殊版本,当呈现元素与当前URL匹配时,它将向呈现元素添加样式属性。
<NavLink to="/about">About</NavLink>
activeClassName: string
当元素处于活动状态时提供该元素的类。默认的给定元素是激活的。这将与className prop连接。
<NavLink to="/faq" activeClassName="selected">
FAQs
</NavLink>
activeStyle: object
当元素处于活动状态时,应用于该元素的样式。
<NavLink
to="/faq"
activeStyle={{
fontWeight: "bold",
color: "red"
}}
>
FAQs
</NavLink>
exact: bool
如果为true,则仅当完全匹配时才会应用组件。
<NavLink exact to="/profile">
Profile
</NavLink>
strict: bool
如果为true,则仅当位置完全匹配时才会应用活动类/样式。如果为true,则在确定位置是否匹配当前URL时,将考虑位置路径名上的尾随斜杠。有关更多信息,请参阅文档。
<NavLink strict to="/events/">
Events
</NavLink>
isActive: func
添加额外逻辑以确定链路是否处于活动状态的函数。如果您想做的不仅仅是验证链接的路径名是否与当前URL的路径名匹配,那么应该使用此选项。
只有isActive返回ture时候,activeStyle才生效。
<NavLink
to="/blog/123"
activeStyle={{
fontWeight: 'bold',
color: 'red',
}}
isActive={(match, location) => {
if (!match) {
return false;
}
console.log(match, location);
// 如果事件ID为奇数,则只考虑活动的事件。
const ID = Math.floor(Math.random() * 100);
return !isNaN(ID) && ID % 2 === 1;
}}
>
Event 123
</NavLink>
location: object
isActive比较当前历史位置(通常是当前浏览器URL)。要与其他位置进行比较,可以传递一个位置。
aria-current: string
活动链接上使用的当前属性的值。可用值包括:
"page"
- used to indicate a link within a set of pagination links"step"
- used to indicate a link within a step indicator for a step-based process"location"
- used to indicate the image that is visually highlighted as the current component of a flow chart"date"
- used to indicate the current date within a calendar"time"
- used to indicate the current time within a timetable"true"
- used to indicate if the NavLink is active"false"
- used to prevent assistive technologies from reacting to a current link (a use case would be to prevent multiple aria-current tags on a single page)
Defaults to "page"
.
<MemoryRouter>
....暂不研究
<Redirect>
重定向,将导航到新位置。新位置将覆盖历史堆栈中的当前位置。
<Route exact path="/">
{loggedIn ? <Redirect to="/dashboard" /> : <PublicHomePage />}
</Route>
to: string
<Redirect to="/somewhere/else" />
to: object
<Redirect
to={{
pathname: "/login",
search: "?utm=your+face",
state: { referrer: currentLocation }
}}
/>
push: bool
如果为true,重定向将在历史记录上推送一个新条目,而不是替换当前条目
<Redirect push to="/somewhere/else" />
from: string
from:
如果路径是/xx to:
跳转到/xxx
如:
<Redirect from="/old-path" to="/new-path" />
则:路径/old-path 重定向 /new-path
<Switch>
<Redirect from="/old-path" to="/new-path" />
<Route path="/new-path">
<Place />
</Route>
</Switch>
// 使用匹配的参数重定向
<Switch>
<Redirect from="/users/:id" to="/users/profile/:id" />
<Route path="/users/profile/:id">
<Profile />
</Route>
</Switch>
exact: bool
精确匹配
<Switch>
<Redirect exact from="/" to="/home" />
<Route path="/home">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
</Switch>
注意:当呈现
<Switch>
内部的<Redirect>
时,这只能与from一起使用,以精确匹配位置。有关更多详细信息,详情reactrouter.com/web/api/Swi…
Route
路由组件可能是React路由器中最重要的组件,它可以帮助您更好地理解和学习如何使用。它最基本的职责是在其路径与当前URL匹配时呈现一些UI。
Route render methods
使用渲染推荐方法是使用childen,但是,您可以使用一些其他方法来使用渲染某些内容。
<Route component>
<Route render>
<Route children>
在给定的上,您应该只使用其中一种渲染方法。
Route props
所有三种渲染方法都将传递相同的三个路由参数
- match
- location
- history
match
match对象包含有关如何匹配URL的信息。匹配对象包含以下属性:
params
- (object) Key/value pairs parsed from the URL corresponding to the dynamic segments of the path(从对应于路径动态段的URL解析的键/值对)isExact
- (boolean)true
if the entire URL was matched (no trailing characters)(是否匹配当前url)path
- (string) The path pattern used to match. Useful for building nested<Route>
(用于匹配路径。)url
- (string) The matched portion of the URL. Useful for building nested<Link>
You’ll have access to match
objects in various places:
在不同的位置获取对象:
- Route component as
this.props.match
- Route render as
({ match }) => ()
- Route children as
({ match }) => ()
- withRouter as
this.props.match
- matchPath as the return value
- useRouteMatch as the return value
location
当前路由信息。看起来是这样的:
{
key: 'ac3df4', // 不是历史!
pathname: '/somewhere',
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}
The router will provide you with a location object in a few places:
路由在以下位置提供对象:
-
Route component as
this.props.location
-
Route render as
({ location }) => ()
-
Route children as
({ location }) => ()
-
withRouter as
this.props.location
You can provide locations instead of strings to the various places that navigate:
您可以为导航的各个位置提供对象信息不是字符串: -
Web Link to
-
Native Link to
-
history.replace 你可能会这样做:
// 通常你所需要的
<Link to="/somewhere"/>
// 但是你可以用一个准确对象来代替
const location = {
pathname: '/somewhere',
state: { fromDashboard: true }
}
<Link to={location}/>
<Redirect to={location}/>
history.push(location)
history.replace(location)
history
React Router提供了 BrowserRouter 和 HashRouter, 用于在各种环境下 JavaScript 管理会话历史。
-
“BrowserRouter” - 特定于 DOM 的实现,在支持 HTML5 历史 API 的 Web 浏览器中很有用
-
“HashRouter” - 旧版 Web 浏览器的特定于 DOM 的实现
history
对象通常具有以下属性和方法: -
length
- (number) 历史堆栈中的条目数 -
action
- (string) 当前动作 (PUSH
,REPLACE
, orPOP
) -
location
- (对象)当前位置。可能具有以下属性:pathname
- (string) URL 的路径search
- (string) URL 查询字符串hash
- (string) URL 哈希片段state
-(对象)特定于位置的状态,例如push(path, state)
当此位置被推送到堆栈时提供。仅在浏览器和内存历史记录中可用。
-
push(path, [state])
-(功能)将新条目推入历史堆栈 -
replace(path, [state])
- (function) 替换历史堆栈中的当前条目 -
go(n)
- (function) 按n
条目移动历史堆栈中的指针 -
goBack()
- (功能)相当于go(-1)
-
goForward()
- (功能)相当于go(1)
-
block(prompt)
-(功能)阻止导航(请参阅历史文档)
component
仅在位置匹配时呈现的 React 组件。它将使用[route props]进行渲染。
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";
const User = (props) => {
return <h1>Hello {props.match.params.username}!</h1>;
}
ReactDOM.render(
<Router>
<Route path="/user/:username" component={User} />
</Router>,
node
);
当您使用component
(而不是render
或children
)时,路由用于从给定的组件React.createElement
创建一个新的React 元素。这意味着如果您为component
prop提供内联函数,您将在每次渲染时创建一个新组件。这会导致卸载现有组件并安装新组件,而不仅仅是更新现有组件。使用内联函数进行内联渲染时,请使用render
或children
道具(如下)。
render: func
render 属性能使你便捷的渲染内联组件或是嵌套组件,你可以给这个属性传入一个函数,当路由的路径匹配时调用,而不是使用 component 创建一个新的 React 元素。同时,render属性也会接受所有由route传入的所有参数。
//内联方式
<Route path="path" render={() => <div>这是内联组件写法</div>} />
//嵌套组合方式
<Route path="path" render={ props => (
<ParentComp>
<Comp {...props} />
</ParentComp>
) />
警告: <Route component>
优先,<Route render>
所以不要在同一个<Route>
.
children: func
children 属性是这三个属性中比较特殊的一个,它的值为一个函数,当 Route 有 children 属性时,不管当前的路径是否与Route匹配,该函数都会执行,同时,children属性也会接受所有由route传入的所有参数。
有时候不论 path 是否匹配位置,你都想渲染一些内容。在这种情况下,你可以使用 children 属性。除了不论是否匹配它都会被调用以外,它的工作原理与 render 完全一样。
children 渲染方式接收所有与 component和 render 方式相同的 route props,除非路由与 URL 不匹配,不匹配时 match 为 null。这允许你可以根据路由是否匹配动态地调整用户界面,如果路由匹配,添加一个激活类。
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Link, Route } from 'react-router-dom';
function ListItemLink(props: any) {
const { to, ...rest } = props;
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>,
document.body
);
警告: <Route children>
优先于两者<Route component>
,<Route render>
因此不要在同一个<Route>
.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
const About = () => {
return <div>component</div>;
};
const Home = () => {
return <div>Home</div>;
};
const App = () => {
let anchorRef = React.createRef();
React.useEffect(() => {
console.log(anchorRef);
}, [anchorRef]);
return (
<>
<BrowserRouter>
<h1>App</h1>
<ul>
<li>
<Link to="/about" ref={anchorRef as any}>
About
</Link>
</li>
<li>
<Link to="/">home</Link>
</li>
</ul>
<Switch>
{/* 渲染children */}
<Route exact={true} path="/about" render={() => <div>'render'</div>} component={About} children={() => <div>'children'</div>} />
{/* 渲染component */}
<Route exact={true} path="/" render={() => <div>'renderHome'</div>} component={Home} />
</Switch>
</BrowserRouter>
</>
);
};
ReactDOM.render(<App />, document.body);
可以得出:
children > component > children
path: string | string[]
能够解析任何有效URL路径或路径数组。
<Route path="/users/:id">
<User />
</Route>
<Route path={["/users/:id", "/profile/:id"]}>
<User />
</Route>
没有路径的路由始终匹配。
exact: bool
当true
, 仅当路径与location.pathname
完全匹配时才匹配。
<Route exact path="/one">
<About />
</Route>
路径 | 位置.路径名 | 准确的 | 匹配? |
---|---|---|---|
/one | /one/two | true | 没有 |
/one | /one/two | false | 是的 |
strict: bool
当 为true
,带有path
尾部斜杠的, a只会匹配location.pathname
带有尾部斜杠 a。当location.pathname
为/one/时候:
<Route strict path="/one/">
<About />
</Route>
路径 | 位置.路径名 | 匹配? |
---|---|---|
/one/ | /one | 没有 |
/one/ | /one/ | 是的 |
/one/ | /one/two | 是的 |
警告: strict
可用于强制 alocation.pathname
没有尾部斜杠,但为了做到这一点strict
,exact
必须是true
.
<Route exact strict path="/one">
<About />
</Route>
路径 | 位置.路径名 | 匹配? |
---|---|---|
/one | /one | 是的 |
/one | /one/ | 没有 |
/one | /one/two | 没有 |
location: object
一个<Route>
元素尝试其匹配path
到当前的历史位置(通常是当前浏览器URL)。但是,也可以传递location
带有不同的 apathname
进行匹配。
当您需要将 a<Route>
与当前历史位置以外的位置匹配时,这很有用,如动画过渡示例所示。
sensitive: bool
如果true
,如果路径是将匹配区分大小写。
<Route sensitive path="/one">
<About />
</Route>
路径 | 位置.路径名 | 敏感 | 匹配? |
---|---|---|---|
/one | /one | true | 是的 |
/One | /one | true | 没有 |
/One | /one | false | 是的 |
Router
所有路由组件的通用低级接口。通常,应用程序将改用其中一个高级路由:
<BrowserRouter>
<HashRouter>
<MemoryRouter>
<NativeRouter>
<StaticRouter>
注意 低级接口,指基本的<Router>
使用低级的最常见用例<Router>
是将自定义历史记录与 Redux 或 Mobx 等状态管理库同步。请注意,这不需要与 React Router 一起使用状态管理库,它仅用于深度集成。
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
console.log(history);
const App = () => {
return <div>app</div>;
};
ReactDOM.render(
<Router history={history}>
<App />
</Router>,
document.body
);
history: object
用于导航的历史对象。
import React from "react";
import ReactDOM from "react-dom";
import { createBrowserHistory } from "history";
const customHistory = createBrowserHistory();
console.log(history);
ReactDOM.render(<Router history={customHistory} />, node);
对象信息:
children: node
要渲染的子元素。
StaticRouter
请移步官网
reactrouter.com/web/api/Sta…
Switch
渲染第一个匹配的[<Route>
]或[<Redirect>
]。
这与仅使用一堆<Route>
有何不同?
<Switch>
它的独特之处在于它专门呈现一条路线。相比之下,每个<Route>
与位置匹配都包含渲染。考虑这些情况:
import { Route } from "react-router";
let routes = (
<div>
<Route path="/about">
<About />
</Route>
<Route path="/:user">
<User />
</Route>
<Route>
<NoMatch />
</Route>
</div>
);
如果 URL 是/about
,则<About>
、<User>
和<NoMatch>
都将呈现,因为它们都与路径匹配。这是设计使然,允许我们以<Route>
多种方式将组合到我们的应用程序中,例如侧边栏和面包屑、引导标签等。
然而,有时我们只想选择一个<Route>
进行渲染。如果我们在,/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>
{/* 匹配404 */}
<Route>
<NoMatch />
</Route>
</Switch>
);
现在,如果我们在/about
,<Switch>
将开始寻找匹配的<Route>
. <Route path="/about"/>
将匹配<Switch>
并将停止寻找匹配和渲染<About>
。同样,如果我们在/michael
then<User>
将渲染。
这对于动画过渡也很有用,因为匹配<Route>
的渲染位置与前一个相同。
let routes = (
<Fade>
<Switch>
{/* 这里永远只会渲染一个Route */}
<Route />
<Route />
</Switch>
</Fade>
);
let routes = (
<Fade>
{/* 这里总有两个孩子,
不过,可能会在进行转换时呈现null
做起来有点麻烦 */}
<Route />
<Route />
</Fade>
);