关于reactjs:使用react路由器以编程方式导航

Programmatically navigate using react router

使用react-router,我可以使用Link元素创建由反应路由器本机处理的链接。

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

我想进行导航,但不是从链接,例如下拉选择。 我怎么能在代码中这样做? 什么是this.context

我看到了Navigation mixin,但我可以不用mixin吗?


React Router v4

使用React Router的v4,您可以采用三种方法在组件内进行编程路由。

  • 使用withRouter高阶组件。
  • 使用合成并渲染
  • 使用context
  • React Router主要是history库的包装器。 history使用浏览器和哈希历史记录处理与浏览器window.history的交互。它还提供了一个内存历史记录,对于没有全局历史记录的环境非常有用。这在移动应用程序开发(react-native)和使用Node的单元测试中特别有用。

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

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

    1.使用withRouter高阶组件

    withRouter高阶组件将history对象注入为组件的prop。这允许您访问pushreplace方法,而无需处理context

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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>
    ))

    2.使用合成并渲染

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import { Route } from 'react-router-dom'

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

    3.使用上下文*

    但你可能不应该这样做

    最后一个选项是您只有在使用React的上下文模型时才能使用的选项。尽管上下文是一种选择,但应该强调上下文是一个不稳定的API,React在其文档中有一节"不使用上下文"。所以使用风险自负!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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 4.0.0+ Answer

    在4.0及更高版本中,使用历史记录作为组件的支柱。

    1
    2
    3
    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+ Answer

    在3.0及以上版本中,使用路由器作为组件的支柱。

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

    React-Router 2.4.0+ Answer

    在2.4及更高版本中,使用更高阶的组件将路由器作为组件的支柱。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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-Router 2.0.0+ Answer

    此版本向后兼容1.x,因此无需升级指南。只是通过这些例子应该足够好了。

    也就是说,如果你想切换到新的模式,路由器内部就有一个browserHistory模块可以访问

    import { browserHistory } from 'react-router'

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

    browserHistory.push('/some/path')

    进一步阅读:
    历史和
    导航

    React-Router 1.x.x Answer

    我不打算升级细节。您可以在"升级指南"中阅读相关内容

    这里问题的主要变化是从导航mixin到History的变化。现在它正在使用浏览器historyAPI来改变路由,所以从现在开始我们将使用pushState()

    这是使用Mixin的例子:

    1
    2
    3
    4
    5
    6
    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-Router 0.13.x Answer

    我遇到了同样的问题,只能通过react-router附带的Navigation mixin找到解决方案。

    这就是我做到的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import React from 'react';
    import {Navigation} from 'react-router';

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

      handleClick(e) {
        e.preventDefault();

        this.transitionTo('/');
      },

      render(){
        return (Click me!);
      }
    });

    我能够在不需要访问.context的情况下调用transitionTo()

    或者你可以尝试花哨的ES6 class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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 (Click me!);
      }
    }

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

    React-Router-Redux

    Note: if you're using Redux, there is another project called
    React-Router-Redux that gives you
    redux bindings for ReactRouter, using somewhat the same approach that
    React-Redux does

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

    探索以下方法:

    • push(location)
    • replace(location)
    • go(number)
    • goBack()
    • goForward()

    以下是使用Redux-Thunk的示例用法:

    ./actioncreators.js

    1
    2
    3
    import { goBack } from 'react-router-redux'

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

    ./viewcomponent.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <button
      disabled={submitting}
      className="cancel_button"
      onClick={(e) => {
        e.preventDefault()
        this.props.onBackPress()
      }}
    >
      CANCEL
    </button>


    React-Router v2

    对于最新版本(v2.0.0-rc5),推荐的导航方法是直接推送到历史单例。您可以在"组件外部导航"文档中看到该操作。

    相关摘录:

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

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

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

    它还提供pushState但每个已记录的警告已弃用。

    如果使用react-router-redux,它提供了一个push函数,您可以这样调度:

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

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


    以下是使用ES6 react-router v2.0.0执行此操作的方法。 react-router已离开mixins。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import React from 'react';

    export default class MyComponent extends React.Component {
      navigateToPage = () => {
        this.context.router.push('/my-route')
      };

      render() {
        return (
          <button onClick={this.navigateToPage}>Go!</button>
        );
      }
    }

    MyComponent.contextTypes = {
      router: React.PropTypes.object.isRequired
    }


    React-Router 4.x Answer :

    在我的结尾,我喜欢有一个历史对象,我甚至可以携带外部组件。我喜欢做的是拥有一个我按需导入的单个history.js文件,并且只是操作它。

    您只需将BrowserRouter更改为路由器,并指定历史记录道具。这不会改变任何事情,除非你有自己的历史对象,你可以根据需要进行操作。

    您需要安装历史记录,react-router使用的库。

    示例用法,ES6表示法:

    history.js

    1
    2
    import createBrowserHistory from 'history/createBrowserHistory'
    export default createBrowserHistory()

    BasicComponent.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import React, { Component } from 'react';
    import history from './history';

    class BasicComponent extends Component {

        goToIndex(e){
            e.preventDefault();
            history.push('/');
        }

        render(){
            return Previous;
        }
    }

    EDIT April 16th, 2018 :

    如果必须从实际从Route组件呈现的组件导航,您还可以从props访问历史记录,如下所示:

    BasicComponent.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import React, { Component } from 'react';

    class BasicComponent extends Component {

        navigate(e){
            e.preventDefault();
            this.props.history.push('/url');
        }

        render(){
            return Previous;
        }
    }


    对于这个,谁不控制服务器端,因此使用哈希路由器v2:

    将您的历史记录放入单独的文件中(例如app_history.js ES6):

    1
    2
    3
    4
    5
    import { useRouterHistory } from 'react-router'
    import { createHashHistory } from 'history'
    const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });

    export default appHistory;

    到处使用它!

    您对react-router(app.js ES6)的入口点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import React from 'react'
    import { render } from 'react-dom'
    import { Router, Route, Redirect } from 'react-router'
    import appHistory from './app_history'
    ...
    const render((
      <Router history={appHistory}>
      ...
      </Router>
    ), document.querySelector('[data-role="app"]'));

    您在任何组件内导航(ES6):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import appHistory from '../app_history'
    ...
    ajaxLogin('/login', (err, data) => {
      if (err) {
        console.error(err); // login failed
      } else {
        // logged in
        appHistory.replace('/dashboard'); // or .push() if you don't need .replace()
      }
    })


    React Router V4

    TL:博士;

    1
    2
    3
    if (navigate) {
      return <Redirect to="/" push={true} />
    }

    简单和声明性的答案是您需要将setState()结合使用

    push: boolean - when true, redirecting will push a new entry onto the history instead of replacing the current one.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import { Redirect } from 'react-router'

    class FooBar extends React.Component {
      state = {
        navigate: false
      }

      render() {
        const { navigate } = this.state

        // here is the important part
        if (navigate) {
          return <Redirect to="/" push={true} />
        }
       // ^^^^^^^^^^^^^^^^^^^^^^^

        return (
         
            <button onClick={() => this.setState({ navigate: true })}>
              Home
            </button>
         
        )
      }
    }

    完整的例子。
    在这里阅读更多。

    PS。该示例使用ES7 +属性初始化程序初始化状态。如果你有兴趣,也可以看看这里。


    Warning: this answer covers only ReactRouter versions before 1.0

    I will update this answer with 1.0.0-rc1 use cases after!

    你也可以不用mixin来做到这一点。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let Authentication = React.createClass({
      contextTypes: {
        router: React.PropTypes.func
      },
      handleClick(e) {
        e.preventDefault();
        this.context.router.transitionTo('/');
      },
      render(){
        return (Click me!);
      }
    });

    上下文的问题在于,除非您在类上定义contextTypes,否则无法访问它。

    至于什么是上下文,它是一个对象,就像道具一样,从父对象传递到子对象,但它是隐式传递下来的,而不必每次都重新声明道具。请参阅https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html


    在事情正常之前我尝试了至少10种方法!

    @Felipe Skinner的withRouter回答对我来说有点压倒性的,我不确定我是否想制作新的"ExportedWithRouter"类名。

    这是最简单,最干净的方法,大约是当前的React-Router 3.0.0和ES6:

    React-Router 3.x.x with ES6:

    1
    2
    3
    4
    5
    6
    7
    8
    import { withRouter } from 'react-router';

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

    // Export the decorated class
    export default withRouter(Example);

    或者,如果它不是您的默认类,则导出如下:

    1
    2
    withRouter(Example);
    export { Example };

    请注意,在3.x.x中,组件本身使用的是router.push,因此您可以传递任何传递标记的内容,例如:

    1
       this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'


    要以编程方式进行导航,您需要将新历史记录推送到component中的props.history,这样这样的事情可以为您完成工作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    //using ES6
    import React from 'react';

    class App extends React.Component {

      constructor(props) {
        super(props)
        this.handleClick = this.handleClick.bind(this)
      }

      handleClick(e) {
        e.preventDefault()
        /* Look at here, you can add it here */
        this.props.history.push('/redirected');
      }

      render() {
        return (
         
            <button onClick={this.handleClick}>
              Redirect!!!
            </button>
         
        )
      }
    }

    export default App;


    请找到以下工作代码:
    正如本文所讨论的,使用react Router进行导航是一种非常简单的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class Register extends React.Component {
      state = {
        toDashboard: false,
      }
      handleSubmit = (user) => {
        saveUser(user)
          .then(() => this.setState(() => ({
            toDashboard: true
          })))
      }
      render() {
        if (this.state.toDashboard === true) {
          return <Redirect to='/dashboard' />
        }

        return (
         
            Register
            <Form onSubmit={this.handleSubmit} />
         
        )
      }
    }

    <重定向/>是

    Composable ? Declarative ? user event -> state change -> re-render ?

    注册组件由React Router呈现,我们的代码看起来像这样

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Register extends React.Component {
      handleSubmit = (user) => {
        saveUser(user).then(() =>
          this.props.history.push('/dashboard')
        ))
      }
      render() {
        return (
         
            Register
            <Form onSubmit={this.handleSubmit} />
         
        )
      }
    }

    通过添加withRouter,它看起来像这样

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import {
      withRouter
    } from 'react-router-dom'

    class Register extends React.Component {
      handleSubmit = (user) => {
        saveUser(user).then(() =>
          this.props.history.push('/dashboard')
        ))
      }
      render() {
        return (
         
            Register
            <Form onSubmit={this.handleSubmit} />
         
        )
      }
    }

    export default withRouter(Register)

    有两种方法可以使用React Router和history.push以编程方式进行导航。您使用的主要取决于您和您的特定用例,尽管我尝试使用Redirect。


    对于ES6 + React组件,以下解决方案适用于我。

    我跟着Felippe skinner,但添加了一个端到端的解决方案,以帮助像我这样的初学者。

    以下是我使用的版本:

    "react-router":"^2.7.0"

    "react":"^15.3.1"

    下面是我的反应组件,我使用react-router进行编程导航:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import React from 'react';

    class loginComp extends React.Component {
       constructor( context) {
        super(context);
        this.state = {
          uname: '',
          pwd: ''
        };
      }

      redirectToMainPage(){
            this.context.router.replace('/home');
      }

      render(){
        return
               // skipping html code
                 <button onClick={this.redirectToMainPage.bind(this)}>Redirect</button>
        ;
      }
    };

     loginComp.contextTypes = {
        router: React.PropTypes.object.isRequired
     }

     module.exports = loginComp;

    以下是我的路由器的配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     import { Router, Route, IndexRedirect, browserHistory } from 'react-router'

     render(<Router history={browserHistory}>
              <Route path='/' component={ParentComp}>
                <IndexRedirect to ="/login"/>
                <Route path='/login' component={LoginComp}/>
                <Route path='/home' component={HomeComp}/>
                <Route path='/repair' component={RepairJobComp} />
                <Route path='/service' component={ServiceJobComp} />
              </Route>
            </Router>, document.getElementById('root'));

    可能不是最好的方法但是......使用react-router v4,下面的Typescript可以给出一些想法。

    在下面的渲染组件中,例如LoginPagerouter对象是可访问的,只需调用router.transitionTo('/homepage')即可导航。

    导航代码取自https://react-router.now.sh/Match。

    "react-router":"^4.0.0-2",
    "react":"^15.3.1",

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    import Router from 'react-router/BrowserRouter';
    import { History } from 'react-history/BrowserHistory';
    import createHistory from 'history/createBrowserHistory';
    const history = createHistory();

    interface MatchWithPropsInterface {
      component: typeof React.Component,
      router: Router,
      history: History,
      exactly?: any,
      pattern: string
    }

    class MatchWithProps extends React.Component<MatchWithPropsInterface,any> {
      render() {
        return(
          <Match {...this.props} render={(matchProps) => (
                 React.createElement(this.props.component, this.props)

            )}
           />
        )
      }
    }

    ReactDOM.render(
        <Router>
          {({ router }) => (
           
              <MatchWithProps exactly pattern="/" component={LoginPage} router={router} history={history} />
              <MatchWithProps pattern="/login" component={LoginPage} router={router} history={history} />
              <MatchWithProps pattern="/homepage" component={HomePage} router={router} history={history} />
              <Miss component={NotFoundView} />
           
          )}
        </Router>,

       document.getElementById('app')
    );


    In React-Router v4 and ES6

    您可以使用withRouterthis.props.history.push

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import {withRouter} from 'react-router-dom';

    class Home extends Component {

        componentDidMount() {
            this.props.history.push('/redirect-to');
        }
    }

    export default withRouter(Home);


    要将withRouter与基于类的组件一起使用,请尝试以下方法。
    不要忘记将export语句更改为使用withRouter

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class YourClass extends React.Component {
      yourFunction = () => {
        doSomeAsyncAction(() =>
          this.props.history.push('/other_location')
        )
      }

      render() {
        return (
         
            <Form onSubmit={ this.yourFunction } />
         
        )
      }
    }

    export default withRouter(YourClass);

    随着React-Router v4的出现,现在有了一种新方法。

    1
    2
    3
    4
    5
    6
    7
    8
    import { MemoryRouter, BrowserRouter } from 'react-router';

    const navigator = global && global.navigator && global.navigator.userAgent;
    const hasWindow = typeof window !== 'undefined';
    const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1;
    const Router = isBrowser ? BrowserRouter : MemoryRouter;

    <Router location="/page-to-go-to"/>

    react-lego是一个示例应用程序,显示如何使用/更新react-router,它包括导航应用程序的示例功能测试。


    根据以前的答案
    来自JoséAntonioPostigo和Ben Wheeler
    新奇?将在Typescript中编写
    和装饰的使用
    或静态属性/字段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    import * as React from"react";
    import Component = React.Component;
    import { withRouter } from"react-router";

    export interface INavigatorProps {
        router?: ReactRouter.History.History;
    }

    /**
     * Note: goes great with mobx
     * @inject("something") @withRouter @observer
     */
    @withRouter
    export class Navigator extends Component<INavigatorProps, {}>{
        navigate: (to: string) => void;
        constructor(props: INavigatorProps) {
            super(props);
            let self = this;
            this.navigate = (to) => self.props.router.push(to);
        }
        render() {
            return (
               
    <ul>

                    <li onClick={() => this.navigate("/home")}>
                        Home
                   
    </li>

                    <li onClick={() => this.navigate("/about")}>
                        About
                   
    </li>

               
    </ul>

            )
        }
    }

    /**
     * Non decorated
     */
    export class Navigator2 extends Component<INavigatorProps, {}> {

        static contextTypes = {
            router: React.PropTypes.object.isRequired,
        };

        navigate: (to: string) => void;
        constructor(props: INavigatorProps, context: any) {
            super(props, context);
            let s = this;
            this.navigate = (to) =>
                s.context.router.push(to);
        }
        render() {
            return (
               
    <ul>

                    <li onClick={() => this.navigate("/home")}>
                        Home
                   
    </li>

                    <li onClick={() => this.navigate("/about")}>
                        About
                   
    </li>

               
    </ul>

            )
        }
    }

    无论今天安装了什么npm。
    "react-router":"^ 3.0.0"和
    "@ types / react-router":"^ 2.0.41"


    在反应路由器v4中。我按照这两种方式以编程方式进行路由。

    1
    2
    1. this.props.history.push("/something/something")
    2. this.props.history.replace("/something/something")

    第二

    Replaces the current entry on the history stack

    要获取道具的历史记录,您可能需要使用包装

    withRouter https://reacttraining.com/react-router/core/api/withRouter


    使用当前的React版本(15.3),this.props.history.push('/location');为我工作,但它显示以下警告:

    browser.js:49 Warning: [react-router] props.history and
    context.history are deprecated. Please use context.router.

    我用这样的context.router解决了它:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import React from 'react';

    class MyComponent extends React.Component {

        constructor(props) {
            super(props);
            this.backPressed = this.backPressed.bind(this);
        }

        backPressed() {
            this.context.router.push('/back-location');
        }

        ...
    }

    MyComponent.contextTypes = {
        router: React.PropTypes.object.isRequired
    };

    export default MyComponent;


    如果您使用哈希或浏览器历史记录,那么您可以这样做

    1
    2
    hashHistory.push('/login');
    browserHistory.push('/login');


    React-Router V4

    如果您使用的是版本4,那么您可以使用我的库(无耻插件),您只需发送一个动作,一切正常!

    1
    dispatch(navigateTo("/aboutUs"));

    https://www.npmjs.com/package/trippler


    那些在react-router v4上实现这个问题的人。

    这是一个工作解决方案,用于从redux操作中导航react应用程序。

    history.js

    1
    2
    3
    import createHistory from 'history/createBrowserHistory'

    export default createHistory()

    App.js / Route.jsx

    1
    2
    3
    4
    5
    6
    import { Router, Route } from 'react-router-dom'
    import history from './history'
    ...
    <Router history={history}>
     <Route path="/test" component={Test}/>
    </Router>

    another_file.js或redux文件

    1
    2
    3
    import history from './history'

    history.push('/test') // this should change the url and re-render Test component

    感谢这个评论:
    ReactTraining发表评论


    如果碰巧通过react-router-redux配对RR4 w / redux,那么使用react-router-redux中的路由操作创建器也是一个选项。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import { push, replace, ... } from 'react-router-redux'

    class WrappedComponent extends React.Component {
      handleRedirect(url, replaceState = true) {
        replaceState
          ? this.props.dispatch(replace(url))
          : this.props.dispatch(push(url))
      }
      render() { ... }
    }

    export default connect(null)(WrappedComponent)

    如果使用redux thunk / saga来管理异步流,则在redux动作中导入上面的动作创建者并使用mapDispatchToProps钩子来反应组件可能会更好。


    也许不是最好的解决方案,但它完成了工作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import { Link } from 'react-router-dom';

    // create functional component Post
    export default Post = () => (
       

            <button className="button delete-post" onClick={() => {
                // ... delete post
                // then redirect, without page reload, by triggering a hidden Link
                document.querySelector('.trigger.go-home').click();
            }}>Delete Post</button>

            <Link to="/" className="trigger go-home hidden"></Link>

       
    );

    基本上,与一个动作相关联的逻辑(在这种情况下是删除后)将最终调用重定向的触发器。这不是理想的,因为您将向标记添加DOM节点"触发器",以便您可以在需要时方便地调用它。此外,您将直接与DOM交互,在可能不需要的React组件中。

    但是,通常不需要这种类型的重定向。因此,组件标记中的一个或两个额外的隐藏链接不会对此造成太大影响,特别是如果您给它们提供有意义的名称。


    在撰写本文时,正确的答案适合我

    1
    this.context.router.history.push('/');

    但是您需要将PropTypes添加到组件中

    1
    2
    3
    4
    Header.contextTypes = {
      router: PropTypes.object.isRequired
    }
    export default Header;

    不要忘记导入PropTypes

    1
    import PropTypes from 'prop-types';


    For React Router v4+

    假设您不需要在初始渲染期间导航(可以使用组件),这就是我们在应用程序中所做的。

    定义一个返回null的空路由,这将允许您获取对历史对象的访问权限。您需要在定义Router的顶层执行此操作。

    现在你可以做所有可以在历史上完成的事情,如history.push()history.replace()history.go(-1)等!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import React from 'react';
    import { HashRouter, Route } from 'react-router-dom';

    let routeHistory = null;

    export function navigateTo(path) {
      if(routeHistory !== null) {
        routeHistory.push(path);
      }
    }

    export default function App(props) {
      return (
        <HashRouter hashType="noslash">
          <Route
            render={({ history }) => {
              routeHistory = history;
              return null;
            }}
          />
          {/* Rest of the App */}
        </HashRouter>
      );
    }

    只需使用this.props.history.push('/where/to/go');即可


    简单的反应路由:

    • https://codesandbox.io/s/lxq0qj7qnl

    链接到我的代码沙箱。
    它还有一些简单的react-redux程序。