react-router(v4)如何返回?


84

试图弄清楚如何返回上一页。我在用[react-router-v4][1]

这是我在第一个登录页面中配置的代码:

<Router>
  <div>
    <Link to="/"><div className="routerStyle"><Glyphicon glyph="home" /></div></Link>
    <Route exact path="/" component={Page1}/>
    <Route path="/Page2" component={Page2}/>
    <Route path="/Page3" component={Page3}/>
  </div>
</Router>

为了转发到后续页面,我只需执行以下操作:

this.props.history.push('/Page2');

但是,如何返回上一页?尝试了以下一些事情,但没有运气:1。this.props.history.goBack();

给出错误:

TypeError:null不是对象(评估“ this.props”)

  1. this.context.router.goBack();

给出错误:

TypeError:null不是对象(评估“ this.context”)

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

给出错误:

TypeError:null不是对象(评估“ this.props”)

Page1在下面发布代码:

import React, {Component} from 'react';
import {Button} from 'react-bootstrap';

class Page1 extends Component {
  constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
  }


  handleNext() {
    this.props.history.push('/page2');
  }

  handleBack() {
    this.props.history.push('/');
  }


  /*
   * Main render method of this class
   */
  render() {
    return (
      <div>
        {/* some component code */}


        <div className="navigationButtonsLeft">
          <Button onClick={this.handleBack} bsStyle="success">&lt; Back</Button>
        </div>
        <div className="navigationButtonsRight">
          <Button onClick={this.handleNext} bsStyle="success">Next &gt;</Button>
        </div>

      </div>
    );
  }


export default Page1;

您尝试了几件事?
Vivek Doshi

3
尝试 this.props.history.goBack(); github.com/ReactTraining/react-router/blob/…–
baskax

@VivekDoshi:添加了我尝试过的内容以及遇到的错误
Akshay Lokur,2017年

@AkshayLokur,请您在尝试执行this.props.history.goBack();的地方张贴完整的代码吗?
Vivek Doshi

@VivekDoshi:完成,请看一看,谢谢
Akshay Lokur

Answers:


119

我认为问题在于绑定:

constructor(props){
   super(props);
   this.goBack = this.goBack.bind(this); // i think you are missing this
}

goBack(){
    this.props.history.goBack();
}

.....

<button onClick={this.goBack}>Go Back</button>

正如我在发布代码之前所假设的那样:

constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
    this.handleBack = this.handleBack.bind(this); // you are missing this line
}

当按下浏览器后退按钮并在componentDidUpdate和中时不起作用window.onpopstate
jmunsch

25
this.props.history.goBack();

这是React-Router v4的正确解决方案

但是您应该牢记的一件事是,您需要确保this.props.history存在。

这意味着您需要在this.props.history.goBack();<Route />包装的组件内部调用此函数

如果在组件树中更深的组件中调用此函数,它将无法正常工作。

编辑:

如果要在组件树中更深的组件中包含历史记录对象(该组件树未由<Route>包裹),可以执行以下操作:

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

class Demo extends Component {
    ...
    // Inside this you can use this.props.history.goBack();
}

export default withRouter(Demo);

那么如何运作?您如何从任何地方追溯历史?
Felipe

@Felipe您可以从任何地方返回。我只是说,您需要在Container组件中添加此行代码才能获取“历史”对象,请不要使用Presentational组件中未被Route包装的代码行(medium.com/@dan_abramov / smart-and-dumb-components-7ca2f9a7c7d0
Hoang Trinh,

@Felipe:嗨,请检查我编辑的答案。我认为它回答了您的问题。
Hoang Trinh '18

感谢您对withRouter进行编辑,为我修复了该问题。
马修·赖德out

17

与DOM树中任何地方的React Router v4和功能组件一起使用。

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

const GoBack = ({ history }) => <img src="./images/back.png" onClick={() => history.goBack()} alt="Go back" />;

export default withRouter(GoBack);

这是一个很好的解决方案,因为它不使用生命周期方法。对我来说,这也很清楚,因为它表示通过的内容,在本例中为历史对象。
AC Patrice

胖箭头版本对我来说总是看起来更干净,为此。
egdavid

9

这里的每个答案都包含整个解决方案的一部分。这是我用来使它能够在比使用Route更深的组件内部工作的完整解决方案:

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'

^您需要第二行来导入功能并导出页面底部的组件。

render() {
  return (
  ...
    <div onClick={() => this.props.history.goBack()}>GO BACK</div>
  )
}

^需要箭头功能与简单的onClick = {this.props.history.goBack()}

export default withRouter(MyPage)

^用'withRouter()'包装您的组件名称


5

您可以在使用的地方提供代码this.props.history.push('/Page2');吗?

您是否尝试过goBack()方法?

this.props.history.goBack();

它在这里列出https://reacttraining.com/react-router/web/api/history

这里有一个实时示例https://reacttraining.com/react-router/web/example/modal-gallery


这给了我错误,请参见上面的更新问题
Akshay Lokur,2017年

您还可以在附近添加代码this.props.history.push('/Page2');吗?如果this.props那里不为null,它应该可以工作。
Alfredo Re

没什么,我只是在组件中单击“后退”按钮来调用它
Akshay Lokur 17-10-11

4

这是您解决此问题的最干净,最简单的方法,它也使的可能的陷阱无效this keyword。使用功能组件:

import { withRouter } from "react-router-dom"; 包装你的component或更好的App.jswithRouter() HOC这使得history可用“的应用范围。” 包装组件只会使history available for that specific组件成为您的选择。

所以你有了:

  1. export default withRouter(App);

  2. 在Redux环境中,export default withRouter( connect(mapStateToProps, { <!-- your action creators -->})(App), );您甚至应该可以通过history这种方式从动作创建者中进行使用。

在您component执行以下操作:

import {useHistory} from react-router-dom;

const history = useHistory(); // do this inside the component

goBack = () => history.goBack();

<btn btn-sm btn-primary onclick={goBack}>Go Back</btn>

export default DemoComponent;

GottchauseHistory仅从最新的v5.1导出,react-router-dom因此请确保更新软件包。但是,您不必担心。关于...的许多障碍this keyword

您还可以使它成为可在整个应用程序中使用的可重用组件。


function BackButton({ children }) {
  let history = useHistory()
  return (
    <button type="button" onClick={() => history.goBack()}>
      {children}
    </button>
  )
}```
Cheers.



2
谢谢。但是,为什么在我返回浏览器时不重新渲染组件?
Stephane

0

尝试:

this.props.router.goBack()

这给了我错误,请参见上面的更新问题
Akshay Lokur,2017年

您从哪里获得路由器或历史记录道具?确保从渲染组件上的父组件或页面(即console.log(this.props))获取它,并检查是否正在打印路由器道具以便能够使用它。
Rodius


0

希望这对某人有帮助:

import React from 'react';
import * as History from 'history';
import { withRouter } from 'react-router-dom';

interface Props {
  history: History;
}

@withRouter
export default class YourComponent extends React.PureComponent<Props> {

  private onBackClick = (event: React.MouseEvent): void => {
    const { history } = this.props;
    history.goBack();
  };

...

0

也许这可以帮助某人。

我过去一直history.replace()在重定向,所以当我尝试使用时history.goBack(),我被发送到上一页而不是在使用该页面之前。因此,我将方法更改为history.replace()history.push()以便可以保存历史记录,并且可以返回。


0

我不确定是否有人遇到此问题或可能需要查看此问题。但是我花了大约3个小时来解决这个问题:

我想在单击按钮时实现一个简单的goBack()。我以为自己开了一个好头,因为我的App.js已经包装在路由器中,并且我正在从“ react-router-dom”导入{BrowserRouter as Router};...由于Router元素允许我评估历史对象。

例如:

import React from 'react';
import './App.css';
import Splash from './components/Splash';
import Header from './components/Header.js';
import Footer from './components/Footer';
import Info from './components/Info';
import Timer from './components/Timer';
import Options from './components/Options';
import { BrowserRouter as Router, Route } from 'react-router-dom';
function App() {
  return (
    <Router>
      <Header />
      <Route path='/' component={Splash} exact />
      <Route path='/home' component={Info} exact />
      <Route path='/timer' component={Timer} exact />
      <Route path='/options' component={Options} exact />
      <Footer />
    </Router>
  );
}
export default App;

但是问题出在我的Nav(子组件)模块上,我不得不“从'react-router-dom';中导入{withRouter};“ 然后使用以下命令强制导出:

export default withRouter(Nav);

例如:

import React from 'react';
import { withRouter } from 'react-router-dom';
class Nav extends React.Component {
    render() {
        return (
            <div>
                <label htmlFor='back'></label>
                <button id='back' onClick={ () => this.props.history.goBack() }>Back</button>
                <label htmlFor='logOut'></label>
                <button id='logOut' ><a href='./'>Log-Out</a>            
</button>
            </div>
        );
    }
}
export default withRouter(Nav);

总而言之,withRouter是由于React中的一个已知问题而创建的,在某些情况下,在某些情况下,拒绝从路由器继承时,必须进行强制导出。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.