如果您的目标是浏览器环境,则需要使用react-router-dom
包,而不是react-router
. 它们遵循与 React 相同的方法,以分离核心 ( react
) 和平台特定代码 ( react-dom
, react-native
),但您不需要安装两个单独的包,因此环境包包含所有内容你需要。您可以将其添加到您的项目中:
yarn add react-router-dom
或者
npm i react-router-dom
您需要做的第一件事是提供一个<BrowserRouter>
作为应用程序中最顶层的父组件。<BrowserRouter>
使用 HTML5 history
API 并为您管理它,因此您不必担心自己实例化它并将其<BrowserRouter>
作为道具传递给组件(正如您在以前的版本中需要做的那样)。
在 V4 中,为了以编程方式导航,您需要访问history
通过 React 可用的对象,context
只要您有一个<BrowserRouter>
提供程序组件作为应用程序中最顶层的父组件。该库通过上下文公开router
对象,该对象本身history
作为属性包含。该history
界面提供了多种导航方法,例如push
、replace
和goBack
等。您可以在此处查看属性和方法的完整列表。
Redux/Mobx 用户的重要提示
如果您在应用程序中使用 redux 或 mobx 作为您的状态管理库,您可能会遇到组件应该具有位置感知能力但在触发 URL 更新后不会重新渲染的问题
发生这种情况是因为使用上下文模型react-router
传递给组件。location
connect 和 observer 都创建组件,其 shouldComponentUpdate 方法对其当前 props 和下一个 props 进行浅比较。这些组件只会在至少一个道具发生变化时重新渲染。这意味着为了确保它们在位置更改时更新,需要为它们提供一个在位置更改时更改的道具。
解决此问题的两种方法是:
- 将连接的组件包装在无路径的
<Route />
. 当前location
对象是 a<Route>
传递给它呈现的组件的道具之一
- 用高阶组件包装连接的组件,实际上具有相同的效果并作为道具 注入
withRouter
location
除此之外,有四种以编程方式导航的方法,按推荐排序:
1.- 使用<Route>
组件
它提倡声明式风格。在 v4 之前,
<Route />
组件被放置在组件层次结构的顶部,必须事先考虑您的路由结构。但是,现在您可以在树中的
任何位置<Route>
拥有组件,从而允许您更好地控制根据 URL 有条件地呈现。将,和as props 注入到您的组件中。导航方法(例如, , ...)可用作对象的属性。
Route
match
location
history
push
replace
goBack
history
有 3 种方法可以使用 、 、 或道具来渲染某些东西Route
,component
但render
不要children
在同一个 . 中使用多个Route
。选择取决于用例,但基本上前两个选项只会在path
与 url 位置匹配时呈现您的组件,而children
无论路径是否与位置匹配,都会呈现组件(对于基于 URL 调整 UI 很有用匹配)。
如果您想自定义组件渲染输出,您需要将组件包装在一个函数中并使用该选项,以便将您想要的任何其他道具传递给您的组件,render
除了和。一个例子来说明:match
location
history
import { BrowserRouter as Router } from 'react-router-dom'
const ButtonToNavigate = ({ title, history }) => (
<button
type="button"
onClick={() => history.push('/my-new-location')}
>
{title}
</button>
);
const SomeComponent = () => (
<Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} />
)
const App = () => (
<Router>
<SomeComponent /> // Notice how in v4 we can have any other component interleaved
<AnotherComponent />
</Router>
);
2.- 使用withRouter
HoC
这个高阶组件将注入与Route
. 但是,它具有每个文件只能有 1 个 HoC 的限制。
import { withRouter } from 'react-router-dom'
const ButtonToNavigate = ({ history }) => (
<button
type="button"
onClick={() => history.push('/my-new-location')}
>
Navigate
</button>
);
ButtonToNavigate.propTypes = {
history: React.PropTypes.shape({
push: React.PropTypes.func.isRequired,
}),
};
export default withRouter(ButtonToNavigate);
3.- 使用Redirect
组件
渲染 a
<Redirect>
将导航到一个新位置。但请记住,
默认情况下,当前位置会被新位置替换,例如服务器端重定向 (HTTP 3xx)。新位置由
to
prop 提供,可以是字符串(要重定向到的 URL)或
location
对象。如果您想
将新条目推送到历史记录中,请同时传递一个
push
道具并将其设置为
true
<Redirect to="/your-new-location" push />
4.-router
通过上下文手动访问
有点气馁,因为
context仍然是一个实验性 API,它可能会在未来的 React 版本中中断/更改
const ButtonToNavigate = (props, context) => (
<button
type="button"
onClick={() => context.router.history.push('/my-new-location')}
>
Navigate to a new location
</button>
);
ButtonToNavigate.contextTypes = {
router: React.PropTypes.shape({
history: React.PropTypes.object.isRequired,
}),
};
毋庸置疑,还有其他路由器组件旨在用于非浏览器生态系统,例如<NativeRouter>
复制内存中的导航堆栈并以 React Native 平台为目标,可通过react-router-native
包获得。
如需进一步参考,请随时查看官方文档。还有一个由该库的一位合著者制作的视频,提供了对 react-router v4 的非常酷的介绍,突出了一些主要变化。