提问者:小点点

使用react router以编程方式导航


使用react-router,我可以使用link元素创建链接,这些链接由react Router本地处理。

我看到它在内部调用this.context.transitionTo(。。。)

我想做个导航。不是从链接,而是从下拉选择(例如)。我怎么用代码来做这件事呢?什么是this.context

我看到了导航mixin,但是我可以在没有mixin的情况下这样做吗?


共3个答案

匿名用户

使用挂钩响应路由器v5.1.0

如果您正在使用React>16.8.0和功能组件,则在React Router>5.1.0中有一个新的usehistory钩子。

import { useHistory } from "react-router-dom";

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

React路由器v4

对于React Router的v4,有三种方法可以用于组件内的编程路由。

  1. 使用withrouter高阶组件。
  2. 使用合成并呈现
  3. 使用上下文

React路由器主要是history库的包装器。history处理与浏览器的window.history的交互,使用浏览器和哈希历史记录。它还提供了内存历史记录,这对于没有全局历史记录的环境很有用。这在移动应用程序开发(react-native)和使用Node的单元测试中特别有用。

history实例有两种导航方法:pushreplace。如果将history视为已访问位置的数组,则push将向数组中添加新位置,而replace将用新位置替换数组中的当前位置。通常,您需要在导航时使用push方法。

在React Router的早期版本中,您必须创建自己的History实例,但在v4中,组件将为您创建浏览器,哈希和内存实例。React Router使与路由器关联的history实例的属性和方法通过Router对象下的上下文可用。

withrouter高阶组件将注入history对象作为组件的道具。这允许您访问pushreplace方法,而不必处理上下文

import { withRouter } from 'react-router-dom'
// this also works with react-router-native

const Button = withRouter(({ history }) => (
  <button
    type='button'
    onClick={() => { history.push('/new-location') }}
  >
    Click Me!
  </button>
))

组件不仅仅用于匹配位置。您可以呈现一条无路径的路由,它将始终与当前位置匹配。组件传递与withrouter相同的道具,因此您将能够通过history道具访问history方法。

import { Route } from 'react-router-dom'

const Button = () => (
  <Route render={({ history}) => (
    <button
      type='button'
      onClick={() => { history.push('/new-location') }}
    >
      Click Me!
    </button>
  )} />
)

但你可能不应该

最后一个选项是只有当您对使用React的上下文模型感到满意时才应该使用的选项(React的上下文API在v16中是稳定的)。

const Button = (props, context) => (
  <button
    type='button'
    onClick={() => {
      // context.history.push === history.push
      context.history.push('/new-location')
    }}
  >
    Click Me!
  </button>
)

// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  })
}

1和2是实现的最简单的选择,因此对于大多数用例来说,它们是您的最佳选择。

匿名用户

React-Router 5.1.0+应答(使用挂钩和React>16.8)

您可以在功能组件上使用新的UseHistory挂钩,并以编程方式导航:

import { useHistory } from "react-router-dom";

function HomeButton() {
  let history = useHistory();
  // use history.push('/some/path') here
};

React-路由器4.0.0+应答

在4.0和更高版本中,使用历史记录作为组件的道具。

class Example extends React.Component {
   // use `this.props.history.push('/some/path')` here
};

注意:如果组件未由呈现,则This.props.history不存在。您应该使用在YourComponent中具有this.props.history

React-Router 3.0.0+应答

在3.0及更高版本中,将路由器用作组件的道具。

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

React-路由器2.4.0+应答

在2.4及以上版本中,使用更高阶的组件来获得路由器作为您组件的道具。

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
var DecoratedExample = withRouter(Example);

// PropTypes
Example.propTypes = {
  router: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  }).isRequired
};

React-路由器2.0.0+应答

此版本与1.x向后兼容,因此不需要升级指南。仅仅看一遍这些例子就足够了。

也就是说,如果您希望切换到新模式,路由器内部有一个浏览器历史模块,您可以使用该模块访问

从“react-router”导入{browserHistory}

现在您可以访问您的浏览器历史记录,因此您可以执行推送,替换等操作。如:

BrowserHistory.Push(“/some/path”)

进一步阅读:历史和导航

React-路由器1.x.x应答

我就不细说升级的细节了。您可以在升级指南中了解这一点

这一问题的主要变化是从导航信息到历史信息的变化。现在它使用浏览器historyAPI更改路由,因此从现在开始我们将使用pushstate()

下面是一个使用mixin的示例:

var Example = React.createClass({
  mixins: [ History ],
  navigateToHelpPage () {
    this.history.pushState(null, `/help`);
  }
})

注意,这个history来自rackt/history项目。而不是从React-Router本身。

如果由于某种原因(可能是因为ES6类)不想使用Mixin,那么您可以从this.props.history访问从路由器获得的历史记录。只有路由器呈现的组件才能访问它。因此,如果您想在任何子组件中使用它,则需要通过props将它作为属性传递。

您可以在其1.0.x文档中阅读有关新版本的更多信息

下面是一个帮助页面,专门介绍如何在组件之外导航

它建议抓取一个引用history=createHistory(),并对其调用replaceState

react-路由器0.13.x应答

我遇到了同样的问题,只能通过React-Router附带的导航混合来找到解决方案。

我是这么做的

import React from 'react';
import {Navigation} from 'react-router';

let Authentication = React.createClass({
  mixins: [Navigation],

  handleClick(e) {
    e.preventDefault();

    this.transitionTo('/');
  },

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

我能够调用transitionTo()而不需要访问.context

或者,您也可以尝试别致的ES6

import React from 'react';

export default class Authentication extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e) {
    e.preventDefault();

    this.context.router.transitionTo('/');
  }

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
}

Authentication.contextTypes = {
  router: React.PropTypes.func.isRequired
};

反应-路由器-还原

注意:如果您正在使用Redux,那么还有一个名为reactrouter-redux的项目可以为ReactRouter提供Redux绑定,使用与ReactRouter相同的方法

React-Router-Redux有几种方法,允许从内部操作创建者进行简单的导航。对于在React Native中拥有现有体系结构的人来说,这些可能特别有用,他们希望在React Web中使用相同的模式,并且具有最小的样板开销。

探索以下方法:

  • 推送(位置)
  • 替换(位置)
  • Go(number)
  • GOBACK()
  • 转发()

下面是一个使用redux-thunk的示例:

。/actioncreators.js

import { goBack } from 'react-router-redux'

export const onBackPress = () => (dispatch) => dispatch(goBack())

。/viewcomponent.js

<button
  disabled={submitting}
  className="cancel_button"
  onClick={(e) => {
    e.preventDefault()
    this.props.onBackPress()
  }}
>
  CANCEL
</button>

匿名用户

React-路由器v2

对于最新的版本(V2.0.0-RC5),推荐的导航方法是直接推入历史单例。您可以在Navigating outside of Components文档中看到这一点。

相关摘录:

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

如果使用较新的react-router API,则需要在组件内部使用this.props中的history,因此:

this.props.history.push('/some/path');

它还提供pushstate,但根据记录的警告,这是不推荐的。

如果使用react-router-redux,它提供了一个push函数,您可以按如下方式分派:

import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));

然而,这可能仅用于更改URL,而不是实际导航到页面。