Come ottenere la cronologia su React-Router v4?


101

Ho qualche piccolo problema durante la migrazione da React-Router v3 a v4. nella v3 sono stato in grado di farlo ovunque:

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

Come ottengo questo in v4.

So che potrei usare, gli withRouteroggetti di scena hoc , React Context o Event Router quando sei in un Component. ma non è il caso per me.

Sto cercando l'equivalenza di NavigatingOutsideOfComponents in v4


1
Grazie @ Chris, ma come ho detto, non sono in Component.
storm_buster

@Chris in una classe di utilità, controlla github.com/ReactTraining/react-router/blob/master/docs/guides/… , potrebbe essere stato un redux middlewarere o qualsiasi altra cosa
storm_buster


Ho finito per utilizzare BrowserRouter come componente principale. In questo modo potrei usare il componente App con Router. Non esattamente quello che mi hai chiesto ma ho gli stessi requisiti e questo è sufficiente per me.
The Fool

Risposte:


180

Hai solo bisogno di avere un modulo che esporta un historyoggetto. Quindi importeresti quell'oggetto in tutto il tuo progetto.

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

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

Quindi, invece di utilizzare uno dei router integrati, useresti il <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')

1
Molte grazie! Al momento, usando react-router4, ho dovuto usare invece questa import in history.js: import createBrowserHistory da 'history / createBrowserHistory';
peter.bartos

3
Ha funzionato per me quando ho inserito history = {history} in Route e passo come un oggetto di scena
Nath Paiva

1
possiamo usare withHistory e ottenere la cronologia negli oggetti di scena piuttosto che creare file separati. questa soluzione non ha funzionato per me con redux.
Zeel Shah

4
Importa createHashHistoryse stavi usando HashRouter.
David Harkness

2
@HassanAzzam Probabilmente stai usando il router React V5 e questa risposta funziona per V4, non per V5. In questo momento ho la stessa sfida e cerco ovunque, ma non riesco a farlo funzionare. history.push al di fuori del componente funziona, ma i clic sul collegamento non funzionano più.
Waterlink

71

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

27
fintanto che sei in un componente. Non sono in un componente
storm_buster

1
Grazie, questo è il modo più semplice e diretto per collegarsi a un altro percorso da un componente. Vorrei solo aggiungere che devi fare this.props.history.push('/some_route');affinché funzioni.
dannytenaglias

1
@storm_buster const Component = props => {... // stuff}e export default withRouter(Component)lavora per me su un componente apolide
Karl Taylor,

10

Similmente alla risposta accettata, ciò che potresti fare è usare reacte react-routerse stesso per fornirti un historyoggetto che puoi definire in un file e quindi esportare.

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

Successivamente, importa Component e monta per inizializzare la variabile della cronologia:

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

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

E poi puoi semplicemente importare nella tua app quando è stata montata:

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`
};

Ho anche creato un pacchetto npm che fa proprio questo.


A partire da reactjs 16.9, questa soluzione emetterà un avviso di deprecazione su componentWillMount e componentWillReceiveProps.
ian

1
@ian true, risolto che
Tomasz Mularczyk

5

Se stai usando redux e redux-thunk, la soluzione migliore sarà usare react-router-redux

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

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

È importante vedere i documenti per eseguire alcune configurazioni.


1
Sono venuto qui sperando di trovare questa soluzione esatta, grazie
vapurrmaid

4

Basandosi su questa risposta se è necessario l'oggetto della cronologia solo per passare ad un altro 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>
  );
}

SBAGLIATO, sei all'interno di un componente. vedi // some-other-file.js dalla risposta accettata
storm_buster il

0

In 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} />}
        /> ...

Quindi in un componente figlio:

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

-2

Nel caso specifico di react-router, l'utilizzo contextè uno scenario di caso valido, ad es

class MyComponent extends React.Component {
  props: PropsType;

  static contextTypes = {
    router: PropTypes.object
  };

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

È possibile accedere a un'istanza della cronologia tramite il contesto del router, ad es this.context.router.history.


La domanda in particolare è chiedere quando si è al di fuori di un componente, quindi this.context non è disponibile come opzione:> "So che potrei usare, l'hoc withRouter, il contesto di reazione o gli oggetti di scena del router di eventi quando sei in un componente. Ma non è il caso per me. "
SunshinyDoyle
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.