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

新手上路,请多包涵

我刚刚将 react-router 从 v3 替换为 v4。

但我不确定如何以编程方式在 Component 的成员函数中导航。即在 handleClick() 函数中,我想在处理一些数据后导航到 /path/some/where 。我曾经这样做过:

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

但是我在 v4 中找不到这样的接口。

如何使用 v4 进行导航?

原文由 Colin Wang 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 661
2 个回答

如果您针对浏览器环境,则需要使用 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 , replacegoBack cdefb74eb45dfa30a —cdefb763等。您可以在 此处查看 属性和方法的完整列表。

Redux/Mobx 用户的重要提示

如果您在应用程序中使用 redux 或 mobx 作为您的状态管理库,您可能会遇到组件应该具有位置感知能力但在触发 URL 更新后不会重新渲染的问题

这是因为 react-routerlocation --- 传递给使用上下文模型的组件。

connect 和 observer 都创建组件,其 shouldComponentUpdate 方法对其当前 props 和下一个 props 进行浅比较。这些组件只会在至少一个道具发生变化时重新渲染。这意味着为了确保它们在位置更改时更新,需要为它们提供一个在位置更改时更改的道具。

解决此问题的两种方法是:

  • 连接 的组件包装在无路径的 <Route /> 中。当前的 location 对象是 <Route> 传递给它呈现的组件的道具之一
  • withRouter 高阶组件包装 连接 的组件,实际上具有相同的效果并注入 location 作为道具

除此之外,有四种以编程方式导航的方法,按推荐排序:

1.- 使用 <Route> 组件

它提倡声明式风格。在 v4 之前, <Route /> 组件被放置在组件层次结构的顶部,必须事先考虑您的路由结构。但是,现在您可以在树中的 任何位置 拥有 <Route> 组件,从而允许您更好地控制根据 URL 有条件地呈现。 Routematch , locationhistory 注入到你的 76623 组件中。 The navigation methods (such as push , replace , goBack …) are available as properties of the history object.

There are 3 ways to render something with a Route , by using either component , render or children props, but don’t use不止一个在同一个 Route 。选择取决于用例,但基本上前两个选项只会在 path 匹配 url 位置时呈现您的组件,而使用 children 组件将呈现无论路径是否匹配位置(对于根据 URL 匹配调整 UI 很有用)。

如果您想自定义组件渲染输出,您需要将组件包装在一个函数中并使用 render 选项,以便将您想要的任何其他道具传递给您的组件,除了 match , locationhistory 。一个例子来说明:

 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 组件

渲染 <Redirect> 将导航到新位置。但请记住, 默认情况下,当前位置会被新位置替换,例如服务器端重定向 (HTTP 3xx)。新位置由 to 提供,可以是字符串(重定向到的 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 的非常酷的介绍,突出了一些主要变化。

原文由 rgommezz 发布,翻译遵循 CC BY-SA 4.0 许可协议

完成它的最简单方法:

this.props.history.push("/new/url")

笔记:

  • 您可能希望将 history prop 从父组件向下传递到您要在其不可用时调用操作的组件。

原文由 Jikku Jose 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进