如果您的目标是浏览器环境,则需要使用react-router-dom
包,而不是react-router
。他们遵循与 React 相同的方法,以分离核心,(react
)和平台特定代码,(react-dom
, react-native
),细微的差别是您不需要安装两个单独的包,因此环境包包含您需要的一切。您可以将其添加到您的项目中,如下所示:
yarn add react-router-dom
or
npm i react-router-dom
您需要做的第一件事是提供<BrowserRouter>
作为应用程序中最顶层的父组件。<BrowserRouter>
使用 HTML5history
API 并为您管理它,因此您不必担心自己实例化它并将其传递给<BrowserRouter>
组件作为道具(正如您在以前的版本中需要做的那样)。
在 V4 中,要以编程方式导航,您需要访问history
对象,可通过 React 获得context
,只要你有一个<BrowserRouter>
provider组件作为应用程序中最顶层的父组件。该库通过上下文公开router
对象,它本身包含history
作为财产。这history
界面提供了多种导航方法,例如push
, replace
and goBack
等。您可以检查属性和方法的完整列表here https://reacttraining.com/react-router/web/api/history.
Redux/Mobx 用户的重要注意事项
If you are using redux or mobx as your state management library in your application, you may have come across issues with components that should be location-aware but are not re-rendered after triggering an URL update
发生这种情况是因为react-router
passes location
使用上下文模型的组件。
connect 和observer 都创建组件,其shouldComponentUpdate 方法会对当前props 和下一个props 进行浅层比较。这些组件只有在至少一个 prop 发生变化时才会重新渲染。这意味着为了确保它们在位置更改时更新,需要为它们提供一个在位置更改时更改的 prop。
解决这个问题的两种方法是:
- 包裹你的连接的无路径中的组件
<Route />
。目前的location
object 是 a 的 props 之一<Route>
传递给它渲染的组件
- 包裹你的连接的组件与
withRouter
高阶组件,实际上具有相同的效果并注入location
作为道具
抛开这一点,有四种以编程方式导航的方法,按推荐排序:
1.- 使用<Route>
成分
It promotes a declarative style. Prior to v4, <Route />
components were placed at the top of your component hierarchy, having to think of your routes structure beforehand. However, now you can have <Route>
components anywhere in your tree, allowing you to have a finer control for conditionally rendering depending on the URL. Route
injects match
, location
and history
as props into your component. The navigation methods (such as push
, replace
, goBack
...) are available as properties of the history
object.
有 3 种方法可以使用 a 来渲染某些内容Route
,通过使用component
, render
or children
道具,但不要在同一个道具中使用多个道具Route
。选择取决于用例,但基本上前两个选项只会在以下情况下渲染您的组件:path
匹配 url 位置,而 withchildren
无论路径是否与位置匹配,组件都会被渲染(对于根据 URL 匹配调整 UI 很有用)。
如果您想自定义组件渲染输出,您需要将组件包装在函数中并使用render
选项,以便将您想要的任何其他道具传递给您的组件,除了match
, location
and 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
这个高阶组件将注入相同的 propsRoute
。但是,它有一个限制,即每个文件只能有 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
成分
Rendering a
<Redirect>
will navigate to a new location. But keep in mind that,
by default, the current location is replaced by the new one, like server-side redirects (HTTP 3xx). The new location is provided by
to
prop, that can be a string (URL to redirect to) or a
location
object. If you want to
push a new entry onto the history instead, pass a
push
prop as well and set it to
true
<Redirect to="/your-new-location" push />
4.- 访问router
通过上下文手动
A bit discouraged because
context https://facebook.github.io/react/docs/context.html is still an experimental API and it is likely to break/change in future releases of 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
包裹。
如需任何进一步的参考,请随时查看官方文档 https://reacttraining.com/react-router/。还有一个video https://www.youtube.com/watch?v=a4kqMQorcnE由该库的一位共同作者制作,它提供了 React-router v4 的非常酷的介绍,强调了一些主要变化。