¿Cómo obtener el historial en react-router v4?

101

Tengo un pequeño problema al migrar de React-Router v3 a v4. en v3 pude hacer esto en cualquier lugar:

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

¿Cómo logro esto en v4.

Sé que me vendría bien, el hocico withRouter , el contexto de reacción o los accesorios del enrutador de eventos cuando estás en un componente. pero no es el caso para mí.

Estoy buscando la equivalencia de NavigatingOutsideOfComponents en v4

Storm_buster
fuente
1
Gracias @Chris, pero como dije, no estoy en Component.
storm_buster
@Chris en una clase de utilidad, consulte github.com/ReactTraining/react-router/blob/master/docs/guides/… , podría haber sido un middlewarere redux o cualquier otra cosa
storm_buster
forma más simple stackoverflow.com/a/53916596/3966458
Saahithyan Vigneswaran
Terminé usando el BrowserRouter como componente raíz. De esa manera podría usar el componente de la aplicación con Router. No es exactamente lo que pediste, pero tengo los mismos requisitos y esto me basta.
The Fool

Respuestas:

180

Solo necesita tener un módulo que exporte un history objeto. Luego, importaría ese objeto a lo largo de su proyecto.

// history.js
import { createBrowserHistory } from 'history'

export default createBrowserHistory({
  /* pass a configuration object here if needed */
})

Luego, en lugar de usar uno de los enrutadores integrados, usaría el <Router>componente.

// index.js
import { Router } from 'react-router-dom'
import history from './history'
import App from './App'

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder)
// some-other-file.js
import history from './history'
history.push('/go-here')
Paul S
fuente
1
¡Muchas gracias! Por el momento, usando react-router4, tuve que usar esta importación en history.js en su lugar: import createBrowserHistory from 'history / createBrowserHistory';
peter.bartos
3
Me funcionó cuando puse history = {history} en Route y paso como un accesorio
Nath Paiva
1
podemos usar withHistory y obtener el historial en accesorios en lugar de crear un archivo separado. esta solución no funcionó para mí con redux.
Zeel Shah
4
Importe createHashHistorysi estaba usando HashRouter.
David Harkness
2
@HassanAzzam Probablemente esté usando react-router V5, y esta respuesta funciona para V4, no para V5. En este momento tengo el mismo desafío y estoy buscando en todas partes, pero no puedo hacerlo funcionar. history.push fuera del componente funciona, pero los clics en el enlace ya no funcionan.
Waterlink
71

¡Esto funciona! https://reacttraining.com/react-router/web/api/withRouter

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

class MyComponent extends React.Component {
  render () {
    this.props.history;
  }
}

withRouter(MyComponent);
Justin Yueh
fuente
27
siempre que esté en un componente. No estoy en un componente
storm_buster
1
Gracias, esta es la forma más fácil y directa de vincular a otra ruta desde un componente. Solo agregaría lo que debe hacer this.props.history.push('/some_route');para que funcione.
dannytenaglias
1
@storm_buster const Component = props => {... // stuff}y export default withRouter(Component)trabaja para mí en un componente sin estado
Karl Taylor
10

De manera similar a la respuesta aceptada, lo que podría hacer es usar reacty él react-routermismo para proporcionarle un historyobjeto que puede incluir en un archivo y luego exportarlo.

history.js

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

// variable which will point to react-router history
let globalHistory = null;

// component which we will mount on top of the app
class Spy extends React.Component {
  constructor(props) {
    super(props)
    globalHistory = props.history; 
  }

  componentDidUpdate() {
    globalHistory = this.props.history;
  }

  render(){
    return null;
  }
}

export const GlobalHistory = withRouter(Spy);

// export react-router history
export default function getHistory() {    
  return globalHistory;
}

Luego, importa el Componente y lo monta para inicializar la variable del historial:

import { BrowserRouter } from 'react-router-dom';
import { GlobalHistory } from './history';

function render() {
  ReactDOM.render(
    <BrowserRouter>
        <div>
            <GlobalHistory />
            //.....
        </div>
    </BrowserRouter>
    document.getElementById('app'),
  );
}

Y luego puede importar en su aplicación cuando se haya montado:

import getHistory from './history'; 

export const goToPage = () => (dispatch) => {
  dispatch({ type: GO_TO_SUCCESS_PAGE });
  getHistory().push('/success'); // at this point component probably has been mounted and we can safely get `history`
};

Incluso hice un paquete npm que hace precisamente eso.

Tomasz Mularczyk
fuente
A partir de reactjs 16.9, esta solución emitirá una advertencia de obsolescencia en componentWillMount y componentWillReceiveProps.
ian
1
@ian cierto, solucionó eso
Tomasz Mularczyk
5

Si está usando redux y redux-thunk, la mejor solución será usar react-router-redux

// then, in redux actions for example
import { push } from 'react-router-redux'

dispatch(push('/some/path'))

Es importante ver los documentos para realizar algunas configuraciones.

Arnold Gandarillas
fuente
1
Vine aquí con la esperanza de encontrar esta solución exacta, gracias
vapurrmaid
4

Basándose en esta respuesta, si necesita un objeto de historial solo para navegar a otro componente:

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>
  );
}
Konrad Grzyb
fuente
INCORRECTO, estás dentro de un componente. ver // some-other-file.js de la respuesta aceptada
storm_buster
0

En App.js

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

 const TheContext = React.createContext(null);

 const App = () => {
   const history = useHistory();

   <TheContext.Provider value={{ history, user }}>

    <Switch>
        <Route exact path="/" render={(props) => <Home {...props} />} />
        <Route
          exact
          path="/sign-up"
          render={(props) => <SignUp {...props} setUser={setUser} />}
        /> ...

Luego, en un componente hijo:

const Welcome = () => {
    
    const {user, history} = React.useContext(TheContext); 
    ....
Ardilla
fuente
-2

En el caso específico de react-router, el uso contextes un escenario de caso válido, p. Ej.

class MyComponent extends React.Component {
  props: PropsType;

  static contextTypes = {
    router: PropTypes.object
  };

  render () {
    this.context.router;
  }
}

Puede acceder a una instancia del historial a través del contexto del enrutador, por ejemplo this.context.router.history.

Gajus
fuente
La pregunta específicamente es sobre cuándo está fuera de un componente, por lo que this.context no está disponible como una opción:> "Sé que podría usar, el hoc withRouter, el contexto de reacción o los accesorios del enrutador de eventos cuando estás en un Componente. Pero no es el caso para mí ".
SunshinyDoyle