小编典典

使用反应路由器 V4 以编程方式导航

all

我刚刚react-router从 v3 更换到 v4。 但我不确定如何以编程方式在 a
的成员函数中导航Component。即在处理一些数据后handleClick()我想导航到的功能。/path/some/where我曾经这样做过:

import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')

但是我在 v4 中找不到这样的接口。
如何使用 v4 进行导航?


阅读 74

收藏
2022-03-28

共1个答案

小编典典

如果您的目标是浏览器环境,则需要使用react-router-dom包,而不是react-router. 它们遵循与 React
相同的方法,以便将核心 ( react) 和平台特定代码 ( react-dom, react-native)
分开,但您不需要安装两个单独的包,因此环境包包含所有内容你需要。您可以将其添加到您的项目中:

yarn add react-router-dom

要么

npm i react-router-dom

您需要做的第一件事是提供一个<BrowserRouter>作为应用程序中最顶层的父组件。<BrowserRouter>使用 HTML5
historyAPI
并为您管理它,因此您不必担心自己实例化它并将其<BrowserRouter>作为道具传递给组件(正如您在以前的版本中需要做的那样)。

在 V4 中,为了以编程方式导航,您需要访问history通过 React 可用的对象,context只要您有一个<BrowserRouter>
提供程序
组件作为应用程序中最顶层的父组件。该库通过上下文公开router对象,该对象本身history作为属性包含。该history界面提供了多种导航方法,例如pushreplacegoBack等。您可以在此处查看属性和方法的完整列表。


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 种方法可以使用 、 、 或道具来渲染某些东西Routecomponentrender不要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.- 使用withRouterHoC

这个高阶组件将注入与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)。新位置由toprop 提供,可以是字符串(要重定向到的 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包获得。

2022-03-28