react-router (v4) ¿cómo volver?

84

Tratando de averiguar cómo puedo volver a la página anterior. estoy usando[react-router-v4][1]

Este es el código que configuré en mi primera página de destino:

<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>

Para reenviar a las páginas siguientes, simplemente hago:

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

Sin embargo, ¿cómo puedo volver a la página anterior? Probé algunas cosas como las que se mencionan a continuación, pero no tuve suerte: 1.this.props.history.goBack();

Da error:

TypeError: null no es un objeto (evaluando 'this.props')

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

Da error:

TypeError: null no es un objeto (evaluando 'this.context')

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

Da error:

TypeError: null no es un objeto (evaluando 'this.props')

Publicando el Page1código aquí a continuación:

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;
Akshay Lokur
fuente
¿Cuáles son las pocas cosas que ha probado?
Vivek Doshi
3
prueba this.props.history.goBack(); github.com/ReactTraining/react-router/blob/…
baskax
@VivekDoshi: Agregué lo que probé junto con los errores que encontré
Akshay Lokur
@AkshayLokur, ¿podría publicar el código completo desde donde está intentando ejecutar this.props.history.goBack () ;?
Vivek Doshi
@VivekDoshi: Listo, por favor eche un vistazo, gracias
Akshay Lokur

Respuestas:

119

Creo que el problema es vinculante:

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>

Como asumí antes de publicar el código:

constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
    this.handleBack = this.handleBack.bind(this); // you are missing this line
}
Vivek Doshi
fuente
no funciona cuando se presiona el botón Atrás del navegador y en componentDidUpdatey window.onpopstate?
jmunsch
25
this.props.history.goBack();

Esta es la solución correcta para react-router v4

Pero una cosa que debe tener en cuenta es que debe asegurarse de que exista this.props.history.

Eso significa que debe llamar a esta función this.props.history.goBack();dentro del componente que está envuelto por <Route />

Si llama a esta función en un componente más profundo en el árbol de componentes, no funcionará.

EDITAR:

Si desea tener un objeto histórico en el componente que está más profundo en el árbol de componentes (que no está envuelto por <Ruta>), puede hacer algo como esto:

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

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

export default withRouter(Demo);
Hoang Trinh
fuente
Entonces, ¿cómo puede funcionar? ¿Cómo se puede volver atrás en la historia desde cualquier lugar?
Felipe
@Felipe Puedes volver desde cualquier lugar. Solo quiero decir que debe agregar esta línea de código en los componentes del contenedor para obtener el objeto "historial", no use esta línea de código de los componentes de presentación que no está envuelto por Route ( medium.com/@dan_abramov / smart-and-dumb-components-7ca2f9a7c7d0 )
Hoang Trinh
@Felipe: Hola, por favor revisa mi respuesta editada. Creo que responde a tu pregunta.
Hoang Trinh
Gracias por la edición de withRouter, que me lo arregló.
Matthew Rideout
17

Para usar con React Router v4 y un componente funcional en cualquier parte del árbol de dom.

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);
frippera
fuente
Ésta es una buena solución porque no utiliza un método de ciclo de vida. También me resulta más claro porque denota lo que pasa, en este caso el objeto histórico.
AC Patrice
La versión de la flecha gorda siempre me parece mucho más limpia, gracias por eso.
egdavid
9

Cada respuesta aquí tiene partes de la solución total. Aquí está la solución completa que usé para que funcione dentro de componentes más profundos que donde se usó Route:

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

^ Necesita esa segunda línea para importar la función y exportar el componente en la parte inferior de la página.

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

^ Requería la función de flecha vs simplemente onClick = {this.props.history.goBack ()}

export default withRouter(MyPage)

^ envuelva el nombre de su componente con 'withRouter ()'

cuatro cuervos
fuente
5

¿Puede proporcionar el código donde usa this.props.history.push('/Page2'); ?

¿Has probado el método goBack ()?

this.props.history.goBack();

Está listado aquí https://reacttraining.com/react-router/web/api/history

Con un ejemplo en vivo aquí https://reacttraining.com/react-router/web/example/modal-gallery

Alfredo Re
fuente
Esto me da un error, consulte la pregunta actualizada anterior
Akshay Lokur
¿También puedes agregar el código this.props.history.push('/Page2');? Si this.propsno es nulo allí, debería funcionar.
Alfredo Re
Nada en realidad, solo llamo a esto al hacer clic en el botón Atrás en mi componente
Akshay Lokur
4

Aquí está la forma más limpia y sencilla de manejar este problema, que también anula las probables trampas del this keyword. Utilice componentes funcionales:

import { withRouter } from "react-router-dom"; envuelva su componento mejor App.jscon withRouter() HOCesto hace historyque esté disponible "en toda la aplicación". envolver su componente solo hacehistory available for that specific componente su elección.

Así que tienes:

  1. export default withRouter(App);

  2. En un entorno Redux export default withRouter( connect(mapStateToProps, { <!-- your action creators -->})(App), );, incluso debería poder utilizar historysus creadores de acciones de esta manera.

en tu componenthaz lo siguiente:

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;

Gottcha useHistorysolo se exporta desde la última versión v5.1, react-router-domasí que asegúrese de actualizar el paquete. Sin embargo, no debería tener que preocuparse. sobre los muchos inconvenientes del this keyword.

También puede convertirlo en un componente reutilizable para usar en su aplicación.


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


Lawrence Eagles
fuente
2
Gracias. Pero, ¿por qué mi componente no se vuelve a renderizar cuando realizo una copia del navegador?
Stephane
0

Tratar:

this.props.router.goBack()
Rodius
fuente
Esto me da un error, consulte la pregunta actualizada anterior
Akshay Lokur
¿De dónde sacas tu enrutador o accesorio de historial? Asegúrese de obtenerlo de su componente principal o página (es decir, console.log (this.props) en la función de renderizado y verifique que esté imprimiendo el accesorio del enrutador para poder usarlo. Me parece que usted no tiene enrutador en su componente.
Rodius
0

Simplemente use

<span onClick={() => this.props.history.goBack()}>Back</span>
IamMHussain
fuente
0

Espero que esto ayude a alguien:

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();
  };

...
Nick Bristol
fuente
0

Quizás esto pueda ayudar a alguien.

Estaba usando history.replace()para redireccionar, así que cuando intenté usar history.goBack(), me enviaron a la página anterior antes de la página con la que estaba trabajando. Así que cambié el método history.replace()para history.push()que el historial se pueda guardar y pueda volver atrás.

Julia Ramos
fuente
0

No estoy seguro de si alguien más se encontró con este problema o podría necesitar verlo. Pero pasé aproximadamente 3 horas tratando de resolver este problema:

Quería implementar un simple goBack () con solo hacer clic en un botón. Pensé que había tenido un buen comienzo porque mi App.js ya estaba incluido en el enrutador y estaba importando {BrowserRouter como enrutador} desde 'react-router-dom'; ... Dado que el elemento Router me permite evaluar el objeto de historial.

ex:

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;

PERO el problema estaba en mi módulo Nav (un componente secundario), tuve que 'importar {withRouter} desde' react-router-dom ';' y luego forzar una exportación con:

export default withRouter(Nav);

ex:

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);

En resumen, withRouter se creó debido a un problema conocido en React donde, en ciertos escenarios, cuando se rechaza la herencia de un enrutador, es necesaria una exportación forzada.

usuario14199788
fuente