使用 React Router V4 以编程方式导航

2024-03-20

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

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

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


如果您的目标是浏览器环境,则需要使用react-router-dom包,而不是react-router。他们遵循与 React 相同的方法,以分离核心,(react)和平台特定代码,(react-dom, react-native),细微的差别是您不需要安装两个单独的包,因此环境包包含您需要的一切。您可以将其添加到您的项目中,如下所示:

yarn add react-router-dom

or

npm i react-router-dom

您需要做的第一件事是提供<BrowserRouter>作为应用程序中最顶层的父组件。<BrowserRouter>使用 HTML5historyAPI 并为您管理它,因此您不必担心自己实例化它并将其传递给<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 />。目前的locationobject 是 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 的非常酷的介绍,强调了一些主要变化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 React Router V4 以编程方式导航 的相关文章

随机推荐

  • 如何为集合提供带有迭代器的 const 接口?

    我想创建一个具有如下签名的函数 Set found to be an iterator to the location of key in map or end if not found bool lookup const Key key
  • 使用 Webbrowser C# 从 iframe 读取 HTML 代码

    如何使用WebBrowser读取IFRAME html代码 我有一个带有 iframe 的网站 点击几次后 新的 URL 会在此 IFRAME 中打开 其中包含 HTML 代码的某些部分 有可能读到这个吗 当我尝试 Navigate 到此
  • 从 GIF 文件的字节数组中提取各个帧的字节数组

    我有一个byte GIF 文件的 我想从中提取所有帧 我可以使用提取帧System Drawing Image and System Drawing Imaging 但这些都需要System Drawing我不能在我的项目中使用它 因为 U
  • 使用 XSLT 转换 Heat 生成的 .wxs(添加RegistryValue 并编辑一些值)

    这是我想要的输出
  • Prolog:覆盖谓词和使用它之间的区别

    我觉得自己真的很愚蠢 感觉自己错过了一些东西 我基本上有两个文件 module pl通用逻辑规则 可重用 state pl一个针对当前场景 在模块文件中 module pl 我已经声明 inside Food Eater T isTime
  • Hadoop MapReduce:可以在一个 hadoop 作业类中定义两个映射器和缩减器吗?

    我有两个独立的 java 类 用于执行两个不同的 MapReduce 作业 我可以独立运行它们 对于这两个作业 它们所操作的输入文件是相同的 所以我的问题是是否可以在一个java类中定义两个映射器和两个缩减器 例如 mapper1 clas
  • 从构造函数初始值设定项抛出异常

    从构造函数初始值设定项抛出异常的最佳方法是什么 例如 class C T0 t0 can be either valid or invalid but does not throw directly T1 t1 heavy object d
  • 为什么查询sqlite数据库时需要创建游标?

    我完全陌生Python sqlite3模块 https docs python org 3 6 library sqlite3 html 以及一般的 SQL 这完全难倒了我 大量缺乏描述cursor objects https docs p
  • 将 JaCoCo 与 SONAR 集成以实现单元和集成测试覆盖

    有没有人尝试使用 ANT 构建配置 JaCoCo 将单元测试和集成测试的覆盖范围转储到 2 个不同的文件中 以便 SONAR 使用它们 这是一个可行的解决方案 为单元测试和集成测试生成报告 该解决方案使用的是append战略 请注意 为了在
  • 具有不同输入的全卷积网络

    我有一个完全卷积神经网络 U Net 可以在下面阅读 https arxiv org pdf 1505 04597 pdf https arxiv org pdf 1505 04597 pdf 我想用它来对图像进行像素分类 我的训练图像有两
  • 无法导入 Materialise CSS JS 反应

    大家 早安 我一直在努力让具体化CSS在我的react app上工作 特别是Javascript文件 我尝试了多种方法 但这是我认为我已经走得更远的一种 在我的 landingpage js 文件中 import React Compone
  • 仅隐藏供应商提供的类的弃用警告

    我们有一个应用程序 其中包含一个非常非常古老的类来连接到专有数据库的 API 此代码会生成大量弃用错误 然后将其记录下来 从而污染我们的日志文件 我们只想基本上忽略此供应商提供的类的弃用错误 但我无法找到执行此操作的最佳方法 我见过的选项
  • Bootstrap:两列居中

    我正在尝试使用 Bootstrap 3 1 实现两列居中布局 我读过这个 如何将 Bootstrap div 与 spanX 类居中 https stackoverflow com questions 9554724 how do i ce
  • 使用 Java 从 Keystore 中导入的证书获取公钥

    我已经创建并下载了证书销售队伍 https ap1 salesforce com 按照中的说明PicketLink 文档 https docs jboss org author display PLINK Picketlink as SP
  • 多租户:每个租户都有单独的数据库

    我们正在开发一个多租户应用程序 在架构方面 我们设计了共享中间层用于业务逻辑 每个租户一个数据库用于数据持久化 也就是说 业务层将为每个租户与数据库服务器建立一组连接 连接池 这意味着应用程序为每个租户维护单独的连接池 如果我们预计大约有
  • Android 画图 PorterDuff.Mode.CLEAR

    我正在开发在 Canvas 上绘图的应用程序 类似于 Android SDK 中的 Finger Paint 演示 我的问题是当我使用时PorterDuff Mode CLEAR 当绘图和画布时 如果我尝试擦除某些内容 它工作正常 但如果我
  • 声明参数化类型同义词的实例

    我有很多适用于向量的函数 即具有类型强制长度的列表 我试图让我的类型更容易编写 即而不是编写 foo Fold Integer v Map Integer Integer v v gt 我正在宣布一个新班级NList所以我可以写foo NL
  • Hibernate JPA 与 JTA 和 Glassfish 应用程序服务器似乎没有提交

    我是 hibernate 的新手 我希望它通过 JNDI 使用来自应用程序服务器的数据库连接 奇怪的是 它在数据库中创建我的表 但不保存实体 看来 它并没有承诺 有人在使用 hibernate 时遇到过类似的问题吗 这是一个小测试 serv
  • 如何将参数传递给graphql查询?

    我正在尝试在 Meteor blaze 项目中使用 Apollo graphql 我正在使用来自swydo blaze apollo 使用graphql查询从mongoDB获取数据就可以了 Using this one can get da
  • 使用 React Router V4 以编程方式导航

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