使用react路由器以编程方式导航

Geo*_*uer 1251 reactjs react-router

随着react-router我可以使用Link元素创建的原生处理反应路由器链接.

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

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

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

Pau*_*l S 1161

反应路由器v4

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

  1. 使用useHistory高阶组件.
  2. 使用组合并渲染a withRouter
  3. 使用<Route>.

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

一个react-native实例有两种导航方法:historypush.如果您将其replace视为已访问位置history的数组,push则会向阵列添加新位置,并使用新位置替换阵列中的当前位置.通常,您需要replace在导航时使用该方法.

在早期版本的阵营路由器,你必须创建自己的push实例,但在第4版的history,<BrowserRouter><HashRouter>组件将创建一个浏览器,哈希和内存的实例为您服务.React Router <MemoryRouter>通过上下文在history对象下提供与路由器关联的实例的属性和方法.

1.使用router高阶组件

withRouter高次成分将注入的withRouter对象作为所述部件的支柱.这使您可以访问historypush方法而无需处理replace.

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

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

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

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}
Run Code Online (Sandbox Code Playgroud)

2.使用构图并渲染a context

<Route>组件不仅适用于匹配位置.您可以渲染无路径路径,它始终与当前位置匹配.该<Route>元件通过同样的道具的<Route>,所以您将能够访问withRouter通过方法history的道具.

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>
))
Run Code Online (Sandbox Code Playgroud)

3.使用上下文*

但你可能不应该这样做

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

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

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

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

  • 什么!?我可以使用`withRouter`而不是通过我的所有组件传递`history`?Gahh我需要花更多时间阅读文档...... (48认同)
  • 我尝试以这种方式使用方法1 withRouter(({history})=> {console.log("hhhhhhhh"); history.push('/ bets')}); 但它从未与路由器4一起使用 (20认同)
  • 如何在不将该行为附加到Button或其他DOM元素的情况下运行`history.push('/ new-location')` (13认同)
  • 从反应16开始,`context`不再是实验性的. (13认同)
  • 更新:对于那些使用 eact-router-dom v6 的人应该使用 useNavigate() 而不是 useHistory()。有关更多详细信息,请参阅以下答案。/sf/answers/4688027501/ (12认同)
  • 抛出错误为'意外使用'历史'无限制全局` (4认同)
  • 仅更新一次。在 v6 中,您需要使用 useNavegate 钩子。从'react-router-dom'导入{useNavigate};常量导航 = useNavigate(); 导航('网址') (2认同)

Fel*_*ner 866

React-Router 4.0.0+答案

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

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

function HomeButton() {
  let history = useHistory();
  // use history.push('/some/path') here
};
Run Code Online (Sandbox Code Playgroud)

React-Router 3.0.0+答案

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

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

React-Router 2.4.0+答案

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

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

React-Router 2.0.0+答案

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

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

useHistory

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

<Route>

进一步阅读: 历史导航


React-Router 1.xx答案

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

这里问题的主要变化是从导航mixin到History的变化.现在它正在使用浏览器historyAPI来改变路线,所以我们<Route path="..." component={YourComponent}/>将从现在开始使用.

这是使用Mixin的例子:

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
};
Run Code Online (Sandbox Code Playgroud)

请注意,这import { browserHistory } from 'react-router'来自rackt/history项目.不是来自React-Router本身.

如果您由于某种原因不想使用Mixin(可能是因为ES6类),那么您可以访问从路由器获得的历史记录browserHistory.push('/some/path').它只能由路由器呈现的组件访问.因此,如果要在任何子组件中使用它,则需要将其作为属性传递下去pushState().

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

这是一个专门关于在组件外部导航的帮助页面

它建议抓住一个引用History并调用this.props.history它.

React-Router 0.13.x答案

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

这就是我做到的

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

props无需访问就可以打电话history = createHistory()

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

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>);
  }
});
Run Code Online (Sandbox Code Playgroud)

反应 - 路由器 - 终极版

注:如果您使用的终极版,有一个名为另一个项目 ReactRouter,终极版,为您提供终极版绑定ReactRouter,有些使用了同样的方法 做出反应,终极版

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

探索以下方法:

  • transitionTo()
  • .context
  • class
  • push(location)
  • replace(location)

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

./actioncreators.js

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
};
Run Code Online (Sandbox Code Playgroud)

./viewcomponent.js

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

export const onBackPress = () => (dispatch) => dispatch(goBack())
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案,接受的答案有点乱,而且很老.@GiantElk我按照2.6.0版本的答案中的说明进行操作. (5认同)
  • 在4.0中,this.props.history不存在。到底是怎么回事? (4认同)
  • 我正在使用`v2.4.0`但是上面提到的方法对我不起作用,我的应用程序根本没有渲染和控制台输出:`未捕获TypeError:(0,_reactRouter.withRouter)不是函数`这里是链接到我的帖子:http://stackoverflow.com/questions/37306166/uncaught-typeerror-0-reactrouter-withrouter-is-not-a-function-when-calling (3认同)
  • 如果您的组件不是由&lt;Route&gt;呈现的,则@ this.props.history不存在@ NicolasS.Xu。您应该使用`&lt;Route path =“ ...” component = {YourComponent} /&gt;`在`YourComponent`中包含`this.props.history`。 (3认同)
  • 我希望 useNavigate 是解决方案,但 6.2.1 版本似乎忽略了“{replace:true}”并且不刷新页面。 (3认同)
  • 对于3.0.x版,还是建议使用此方法?许多人似乎使用“上下文”方式。 (2认同)

Bob*_*bby 496

React-Router v2

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

相关摘录:

import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
Run Code Online (Sandbox Code Playgroud)

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

this.props.history.push('/some/path');
Run Code Online (Sandbox Code Playgroud)

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

如果使用react-router-redux,它提供了一个push你可以调度的功能:

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

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

  • 不要忘记较新的API不使用'./ react-router'`中的`import {browserHistory},而是使用'history/lib/createBrowserHistory'中的`import createBrowserHistory创建历史记录.稍后,您可以从组件props访问`history`:`this.props.history('/ some/path')` (14认同)
  • react-router-redux`push`仅更改URL,实际上不会更改页面.要做到这两点,从`react-router`导入`browserHistory`并使用`browserHistory.push('/ my-cool-path')`.不幸的是,这不容易找到.https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md (7认同)
  • `var browserHistory = require('react-router').browserHistory; browserHistory.goBack();` (6认同)
  • 我正在使用this.props.history.push('/')但只有URL被更改...这里没有实际的路由.我错过了什么? (4认同)
  • 我刚刚上传了我的观点[如何在最新的“反应路由器” v4中以编程方式进行导航](http://stackoverflow.com/questions/39894547/navigating-programatically-in-react-router-v4/39894548#39894548) (2认同)

Ale*_*ler 51

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

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
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信目前的建议是使用@Bobby所述的`history`单身人士.你*可以*使用`context.router`,但是你很难将这些组件单元测试为实例化*just*该组件在上下文中不会有这个. (5认同)
  • @GeorgeMauer我认为这取决于代码在哪里运行。根据react docs,如果context.router在服务器上运行,则建议使用它。https://github.com/reactjs/react-router/blob/master/upgrade-guides/v2.0.0.md#navigating-inside-deeply-nested-components (2认同)

Eri*_*tin 42

React-Router 4.x答案:

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

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

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

示例用法,ES6表示法:

history.js

import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory()
Run Code Online (Sandbox Code Playgroud)

BasicComponent.js

import React, { Component } from 'react';
import history from './history';

class BasicComponent extends Component {

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

    render(){
        return <a href="#" onClick={this.goToIndex}>Previous</a>;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑2018年4月16日:

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

BasicComponent.js

import React, { Component } from 'react';

class BasicComponent extends Component {

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

    render(){
        return <a href="#" onClick={this.navigate}>Previous</a>;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 除了React Router文档告诉我们,在大多数情况下,您不需要使用`Router`而不是`BrowserRouter`。“ BrowserRouter”会为您创建并维护“ history”对象。仅当您[[需要与Redux之类的状态管理工具进行深度集成]时,您才不应默认创建自己的文件。https://reacttraining.com/react-router/web/api/Router (2认同)
  • 这是我从时间和经验中学到的东西。虽然使用默认的`this.props.history`通常是一个好习惯,但我还没有找到一种解决方案可以帮助我在不是组件或任何其他非组件工具的类中执行此操作作为React组件构建的,您可以将props传递给该组件。感谢您的反馈意见 :) (2认同)

Ale*_*dko 37

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

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

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

export default appHistory;
Run Code Online (Sandbox Code Playgroud)

到处使用它!

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

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"]'));
Run Code Online (Sandbox Code Playgroud)

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

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()
  }
})
Run Code Online (Sandbox Code Playgroud)

  • 为什么这个答案不是最好的?为什么要使用Context或HOC或事件原型来解决所有麻烦,为什么不仅仅导入历史记录并在我们喜欢的任何地方使用呢?只是想了解权衡 (4认同)
  • 当您使用“哈希”导航时,在“反应路由器” v2中,您需要安装其他模块“历史”(如果要避免奇怪的哈希查询),而不是使用browserHistory,则需要使用useRouterHistory(createHashHistory)( {queryKey:false})。这是我发布此消息的主要原因。我展示了如何浏览哈希历史记录。 (2认同)

Lyu*_*mir 33

反应路由器V4

TL:博士;

if (navigate) {
  return <Redirect to="/" push={true} />
}
Run Code Online (Sandbox Code Playgroud)

简单而陈述的答案是你需要<Redirect to={URL} push={boolean} />结合使用setState()

push:boolean -当为true时,重定向将把新条目推送到历史记录而不是替换当前的条目.


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 (
      <div>
        <button onClick={() => this.setState({ navigate: true })}>
          Home
        </button>
      </div>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Qim*_*ing 28

警告:此答案仅涵盖1.0之前的ReactRouter版本

我将用1.0.0-rc1用例更新此答案!

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

let Authentication = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  handleClick(e) {
    e.preventDefault();
    this.context.router.transitionTo('/');
  },
  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});
Run Code Online (Sandbox Code Playgroud)

带有上下文的问题是除非你contextTypes在类上定义它,否则它是不可访问的.

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


Ben*_*ler 24

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

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

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

带有ES6的React-Router 3.xx:

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);
Run Code Online (Sandbox Code Playgroud)

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

withRouter(Example);
export { Example };
Run Code Online (Sandbox Code Playgroud)

请注意,在3.xx中,<Link>组件本身正在使用router.push,因此您可以传递任何您传递<Link to=标签的内容,例如:

   this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'
Run Code Online (Sandbox Code Playgroud)

  • 它也可以与 @withRouter 一起用作类装饰器......与 mobx 搭配得很好 (2认同)

zil*_*nas 23

对于那些已经在使用 React Router v6 的人,可以useNavigate使用react-router.

使用这个钩子进行导航非常简单:

import { generatePath, useNavigate } from 'react-router';

navigate(-1); // navigates back
navigate('/my/path'); // navigates to a specific path
navigate(generatePath('my/path/:id', { id: 1 })); // navigates to a dynamic path, generatePath is very useful for url replacements
Run Code Online (Sandbox Code Playgroud)


Has*_*eed 21

对于最新的react-router-dom v6

useHistory()被替换为useNavigate().

您需要使用:

import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('/your-page-link');
Run Code Online (Sandbox Code Playgroud)


Ali*_*eza 20

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

//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 (
      <div>
        <button onClick={this.handleClick}>
          Redirect!!!
        </button>
      </div>
    )
  }
}

export default App;
Run Code Online (Sandbox Code Playgroud)


Sof*_*ddy 18

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

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

以下是我使用的版本:

"react-router":"^ 2.7.0"

"反应":"^ 15.3.1"

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

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 <div>
           // skipping html code 
             <button onClick={this.redirectToMainPage.bind(this)}>Redirect</button>
    </div>;
  }
};

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

 module.exports = loginComp;
Run Code Online (Sandbox Code Playgroud)

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

 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'));
Run Code Online (Sandbox Code Playgroud)


mck*_*cku 18

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

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

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

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

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 }) => (
        <div>
          <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} />
        </div>
      )}
    </Router>,

   document.getElementById('app')
);
Run Code Online (Sandbox Code Playgroud)


Hos*_*ein 16

React-Router v4ES6中

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

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

class Home extends Component {

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

export default withRouter(Home);
Run Code Online (Sandbox Code Playgroud)

  • 已经在其他几个答案中提及(包括最前面的答案中的详细内容) (2认同)

Jan*_*nos 13

withRouter与基于类的组件一起使用,请尝试以下方法.不要忘记更改要使用的导出语句withRouter:

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

class YourClass extends React.Component {
  yourFunction = () => {
    doSomeAsyncAction(() =>
      this.props.history.push('/other_location')
    )
  }

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

export default withRouter(YourClass);
Run Code Online (Sandbox Code Playgroud)


pet*_*and 10

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

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"/>
Run Code Online (Sandbox Code Playgroud)

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

  • 这非常适合从渲染功能导航,但我想知道如何从生命周期钩子或redux等导航? (5认同)

Dan*_*Dan 10

根据
JoséAntonioPostigo和Ben Wheeler 之前的回答,
这个新奇事物?是要在Typescript编写
并使用装饰器
OR 静态属性/字段

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>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

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


sai*_*945 10

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

1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")
Run Code Online (Sandbox Code Playgroud)

第二

替换历史堆栈上的当前条目

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

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


Vij*_*122 10

带有钩子的 React Router v6

import {useNavigate} from 'react-router-dom';
let navigate = useNavigate();
navigate('home');
Run Code Online (Sandbox Code Playgroud)

并在浏览器历史记录中移动,

navigate(-1); ---> Go back
navigate(1);  ---> Go forward
navigate(-2); ---> Move two steps backward.
Run Code Online (Sandbox Code Playgroud)


Zam*_*zal 8

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

hashHistory.push('/login');
browserHistory.push('/login');
Run Code Online (Sandbox Code Playgroud)

  • `hashHistory.push`,给出了无法读取未定义的属性“ push”。您从哪里导入这些? (2认同)

Nic*_*yme 8

您还可以useHistory在无状态组件中使用钩子。文档中的示例:

import { useHistory } from "react-router"

function HomeButton() {
  const history = useHistory()

  return (
    <button type="button" onClick={() => history.push("/home")}>
      Go home
    </button>
  )
}
Run Code Online (Sandbox Code Playgroud)

注意:添加了钩子react-router@5.1.0并且需要react@>=16.8


Jos*_*igo 7

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

browser.js:49警告:[react-router] props.history并且 context.history已弃用.请使用context.router.

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

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;
Run Code Online (Sandbox Code Playgroud)


JJ_*_*ire 7

这对我有用,不需要特殊导入:

<input 
  type="button" 
  name="back" 
  id="back" 
  class="btn btn-primary" 
  value="Back" 
  onClick={() => { this.props.history.goBack() }} 
/>
Run Code Online (Sandbox Code Playgroud)


小智 7

以编程方式在基于类的组件中导航。

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

class MyComponent extends React.Component{
    state = {rpath: null}

    const goTo = (path) => this.setState({rpath: path});

    render(){
        if(this.state.rpath){
            return <Redirect to={this.state.rpath}/>
        }
        .....
        .....
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

为了简单起见,只需使用useNavigate最新版本的 React

新文件.js

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

const Newfile = () => {
    const navigate = useNavigate();
   
    ....

    navigate("yourdesiredlocation");

    ....
}

export default Newfile;
Run Code Online (Sandbox Code Playgroud)

在您的代码中使用useNavigate上述功能。


Gar*_*lor 6

React-Router V4

如果您使用的是版本4,则可以使用我的库(Shameless插件),您可以在其中简单地调度一个动作,并且一切正常!

dispatch(navigateTo("/aboutUs"));
Run Code Online (Sandbox Code Playgroud)

特里普勒


web*_*ter 6

在撰写本文时,正确答案是给我的

this.context.router.history.push('/');
Run Code Online (Sandbox Code Playgroud)

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

Header.contextTypes = {
  router: PropTypes.object.isRequired
}
export default Header;
Run Code Online (Sandbox Code Playgroud)

不要忘记导入 PropTypes

import PropTypes from 'prop-types';
Run Code Online (Sandbox Code Playgroud)


Ste*_*Bob 6

试试React Hook Router,“react-router 的现代替代品”:

import { useRoutes, usePath, A} from "hookrouter";
Run Code Online (Sandbox Code Playgroud)

要回答 OP 关于通过选择框链接的问题,您可以这样做:

navigate('/about');
Run Code Online (Sandbox Code Playgroud)

更新答案

我认为 React Hook Router 是一个很好的入门工具包,它帮助我学习了路由,但我已经更新到React Router以了解其历史记录和查询参数处理。

import { useLocation, useHistory } from 'react-router-dom';


const Component = (props) => {
    const history = useHistory();

    // Programmatically navigate
    history.push(newUrlString);
}
Run Code Online (Sandbox Code Playgroud)

您将要导航到的位置推送到 location.history。


nea*_*tsu 5

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

import { Link } from 'react-router-dom';

// Create functional component Post
export default Post = () => (
    <div className="component 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>

    </div>
);
Run Code Online (Sandbox Code Playgroud)

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

不过,这种类型的重定向并不经常需要。因此,组件标记中的一两个额外的、隐藏的链接不会造成太大伤害,尤其是如果您给它们起有意义的名称。


Xle*_*lee 5

如果您碰巧通过react-router-redux将 RR4 与 redux 配对,react-router-redux也可以选择使用路由操作创建者。

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)
Run Code Online (Sandbox Code Playgroud)

如果您使用 redux thunk/saga 来管理异步流,那么在 redux 动作中导入上述动作创建者并使用 mapDispatchToProps 挂钩到 React 组件可能会更好。


ref*_*ity 5

那些在react-router v4上实现此功能时遇到问题的人。

这是一个用于从redux动作浏览react应用程序的可行解决方案。

history.js

import createHistory from 'history/createBrowserHistory'

export default createHistory()
Run Code Online (Sandbox Code Playgroud)

App.js / Route.jsx

import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
 <Route path="/test" component={Test}/>
</Router>
Run Code Online (Sandbox Code Playgroud)

another_file.js或redux文件

import history from './history' 

history.push('/test') // this should change the url and re-render Test component
Run Code Online (Sandbox Code Playgroud)

感谢此评论: ReactTraining问题评论


Aft*_*han 5

对于 React 路由器 v4+

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

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

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

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>
  );
}
Run Code Online (Sandbox Code Playgroud)


nor*_*ial 5

在我的回答中,可以通过三种不同的方式以编程方式重定向到路由。已经介绍了一些解决方案,但以下解决方案仅针对具有附加演示应用程序的功能组件

使用以下版本:

反应:16.13.1

反应域:16.13.1

反应路由器:5.2.0

反应路由器-dom:5.2.0

打字稿:3.7.2

配置:

所以首先解决方案是使用HashRouter,配置如下:

<HashRouter>
    // ... buttons for redirect

    <Switch>
      <Route exact path="/(|home)" children={Home} />
      <Route exact path="/usehistory" children={UseHistoryResult} />
      <Route exact path="/withrouter" children={WithRouterResult} />
      <Route exact path="/redirectpush" children={RedirectPushResult} />
      <Route children={Home} />
    </Switch>
</HashRouter>
Run Code Online (Sandbox Code Playgroud)

文档有关<HashRouter>

一个<Router>使用该URL(即哈希部分window.location.hash),以确保您的UI同步与URL。

解决方案:

  1. 使用<Redirect>推送使用useState

在功能组件(RedirectPushAction来自我的存储库的组件)中使用我们可以useState用来处理重定向。棘手的部分是一旦重定向发生,我们需要将redirect状态设置回false. 通过延迟使用setTimeOut0我们等待 React 提交Redirect到 DOM,然后取回按钮以便下次使用它。

请在下面找到我的示例:

const [redirect, setRedirect] = useState(false);
const handleRedirect = useCallback(() => {
    let render = null;
    if (redirect) {
        render = <Redirect to="/redirectpush" push={true} />

        // In order wait until committing to the DOM
        // and get back the button for clicking next time
        setTimeout(() => setRedirect(false), 0);
    }
    return render;
}, [redirect]);

return <>
    {handleRedirect()}
    <button onClick={() => setRedirect(true)}>
        Redirect push
    </button>
</>
Run Code Online (Sandbox Code Playgroud)

<Redirect>文档:

渲染 a<Redirect>将导航到新位置。新位置将覆盖历史堆栈中的当前位置,就像服务器端重定向 (HTTP 3xx) 那样。

  1. 使用useHistory钩子:

在我的解决方案中有一个名为的组件UseHistoryAction,它代表以下内容:

let history = useHistory();

return <button onClick={() => { history.push('/usehistory') }}>
    useHistory redirect
</button>
Run Code Online (Sandbox Code Playgroud)

useHistory钩让我们访问历史记录对象,这有助于我们编程导航或更改路线。

  1. 使用withRouterhistoryprops

创建了一个名为 的组件WithRouterAction,显示如下:

const WithRouterAction = (props:any) => {
    const { history } = props;

    return <button onClick={() => { history.push('/withrouter') }}>
        withRouter redirect
    </button>
}

export default withRouter(WithRouterAction);
Run Code Online (Sandbox Code Playgroud)

withRouter文档中读取:

您可以通过高阶组件访问history对象的属性和最接近<Route>的匹配项withRouter。每当它呈现时,withRouter都会将 updated matchlocationhistoryprops 传递给包装的组件。

演示:

为了更好地表达,我用这些示例构建了一个 GitHub 存储库,请在下面找到它:

React Router 以编程方式重定向示例


归档时间:

查看次数:

634613 次

最近记录:

5 年,9 月 前