Jak przejść do historii w React Router v4?

360

W bieżącej wersji React Router (v3) mogę zaakceptować odpowiedź serwera i użyć, browserHistory.pushaby przejść do odpowiedniej strony odpowiedzi. Nie jest to jednak dostępne w wersji 4 i nie jestem pewien, jaki jest właściwy sposób obsługi tego.

W tym przykładzie przy użyciu Redux wywołanie składników / app-product-form.jsthis.props.addProduct(props) po przesłaniu formularza przez użytkownika. Gdy serwer zwróci sukces, użytkownik zostaje przeniesiony na stronę koszyka.

// actions/index.js
export function addProduct(props) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
      .then(response => {
        dispatch({ type: types.AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/cart'); // no longer in React Router V4
      });
}

Jak mogę przekierować na stronę Koszyk z funkcji React Router v4?

Chris
źródło
Aby dodać do tego ostatnie oferowane rozwiązanie i sugestie w problemach React Routera w GitHub, użycie polecenia contextręcznego przekazania tego, czego potrzebujesz ręcznie, jest „nie do zrobienia”. O ile nie jestem autorem biblioteki, nie powinno być potrzeby jej używania. W rzeczywistości Facebook odradza to.
Chris
@Chris znalazłeś rozwiązanie tego problemu? muszę przejść do innego komponentu w akcji, tak jak to tutaj wyjaśniłeś
Mr.G
@ Mr.G, niestety nie mam. Ostatnio czytałem, że zespół React Training utrzymuje, że React Router ma dostępny pakiet redux. Nie miałem szczęścia sprawić, by działało i nie włożyli dużo pracy w rozwiązanie tego problemu.
Chris
Dlaczego nie możemy użyć windows.location.href = URL? Czy jest coś złego w używaniu go do zmiany adresu URL i przekierowania?
Shan,
Nie rozumiem, dlaczego nie, ale opcja użycia historydziała również dla React Native jako opcja, a także dodatkowa opcja obsługi starszych przeglądarek.
Chris,

Odpowiedzi:

308

Możesz korzystać z historymetod poza komponentami. Spróbuj w następujący sposób.

Najpierw utwórz historyobiekt wykorzystujący pakiet historii :

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

Następnie zawiń go <Router>( pamiętaj , że powinieneś użyć import { Router }zamiast import { BrowserRouter as Router }):

// src/index.jsx

// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/login">Login</Link></li>
        </ul>
        <Route exact path="/" component={HomePage} />
        <Route path="/login" component={LoginPage} />
      </div>
    </Router>
  </Provider>,
  document.getElementById('root'),
);

Zmień swoją bieżącą lokalizację z dowolnego miejsca, na przykład:

// src/actions/userActionCreators.js

// ...
import history from '../history';

export function login(credentials) {
  return function (dispatch) {
    return loginRemotely(credentials)
      .then((response) => {
        // ...
        history.push('/');
      });
  };
}

UPD : Możesz również zobaczyć nieco inny przykład w React Router FAQ .

Oleg Belostotsky
źródło
24
Próbowałem zrobić dokładnie to, co powiedział @OlegBelostotsky, ale potem history.push('some path')adres URL się zmienia, ale strona się nie zmienia. Muszę umieścić window.location.reload()go w niektórych częściach mojego kodu, aby działał. Jednak w jednym przypadku muszę zachować drzewo stanu redux i przeładowanie go niszczy. Jakieś inne rozwiązanie?
sdabrutas
2
@idunno Spróbuj użyć withRouterkomponentu wyższego rzędu.
Oleg Belostotsky
To rzuciło mi błąd stwierdzający: createBrowserHistory nie jest funkcją. Co mogę zrobić?
AKJ
@AKJ Może import createHistory from 'history/createBrowserHistory'; export default createHistory();będzie praca.
Oleg Belostotsky
1
Przepraszamy za opinię :). Chociaż powinno to również działać, poprawnym sposobem radzenia sobie z tym jest Chris: stackoverflow.com/a/42716055/491075 .
gion_13
340

React Router v4 zasadniczo różni się od v3 (i wcześniejszych) i nie możesz robić tego, browserHistory.push()co kiedyś.

Ta dyskusja wydaje się powiązana, jeśli chcesz uzyskać więcej informacji:

  • Utworzenie nowego browserHistorynie zadziała, ponieważ <BrowserRouter>tworzy własną instancję historii i nasłuchuje zmian. Dlatego inna instancja zmieni adres URL, ale nie zaktualizuje <BrowserRouter>.
  • browserHistory nie jest narażony przez router-reakcyjny w wersji 4, tylko w wersji 2.

Zamiast tego masz kilka opcji:

  • Użyj withRouterkomponentu wyższego rzędu

    Zamiast tego należy użyć withRouterkomponentu wyższego rzędu i zawinąć go w komponent, który przejdzie do historii. Na przykład:

    import React from "react";
    import { withRouter } from "react-router-dom";
    
    class MyComponent extends React.Component {
      ...
      myFunction() {
        this.props.history.push("/some/Path");
      }
      ...
    }
    export default withRouter(MyComponent);

    Sprawdź oficjalną dokumentację, aby uzyskać więcej informacji:

    Możesz uzyskać dostęp do historywłaściwości obiektu i najbliższa <Route>„s matchpoprzez komponent wyższego rzędu withRouter. withRouter ponownie uczynić jego skład każdym razem trasa zmienia się z tych samych rekwizytów jak <Route>czynią rekwizyty: { match, location, history }.


  • Użyj contextinterfejsu API

    Korzystanie z kontekstu może być jednym z najprostszych rozwiązań, ale jako eksperymentalny interfejs API jest niestabilny i nie jest obsługiwany. Używaj go tylko wtedy, gdy wszystko inne zawiedzie. Oto przykład:

    import React from "react";
    import PropTypes from "prop-types";
    
    class MyComponent extends React.Component {
      static contextTypes = {
        router: PropTypes.object
      }
      constructor(props, context) {
         super(props, context);
      }
      ...
      myFunction() {
        this.context.router.history.push("/some/Path");
      }
      ...
    }

    Zobacz oficjalną dokumentację dotyczącą kontekstu:

    Jeśli chcesz, aby aplikacja była stabilna, nie używaj kontekstu. Jest to eksperymentalny interfejs API i prawdopodobnie zepsuje się w przyszłych wydaniach React.

    Jeśli nalegasz na używanie kontekstu pomimo tych ostrzeżeń, spróbuj odizolować użycie kontekstu na małym obszarze i unikaj bezpośredniego korzystania z kontekstowego interfejsu API, jeśli to możliwe, aby łatwiej było uaktualnić, gdy zmieni się interfejs API.

Chris
źródło
9
Tak, spróbowałem. Dzięki, że pytasz. :-) Więc jak wprowadzić kontekst w tę funkcję akcji? Jak dotąd wydaje się, że jest niezdefiniowany.
Chris
1
Badam ten temat od kilku dni i nie udało mi się go uruchomić. Nawet korzystając z powyższego przykładu ciągle otrzymuję, że router jest niezdefiniowany w tym kontekście. Obecnie używam React v15.5.10, React-router-dom v4.1.1, Prop-typy 15.5.10. Dokumentacja wokół tego jest rzadka i niezbyt jasna.
Stu
5
@Stu to powinno działaćthis.context.router.history.push('/path');
Tushar Khatiwada,
1
@Chris Rzeczywiście, jeśli spróbujesz utworzyć instancję obiektu historii i użyć go samodzielnie, zmieni on adres URL, ale nie wyświetli komponentu - jak wspomniano powyżej. Ale jak użyć „history.push” poza komponentem i wymusić renderowanie komponentu?
fajne
52
To nie odpowiada na zadane pytanie, jak uzyskać dostęp do history.push OUTSIDE komponentu. Używanie z routerem lub kontekstem nie jest opcją, gdy znajduje się poza komponentem.
SunshinyDoyle,
49

Teraz z React-Router v5 możesz użyć haka cyklu życia useHistory w następujący sposób:

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

czytaj więcej na: https://reacttraining.com/react-router/web/api/Hooks/usehistory

Hadi Abu
źródło
1
To bardzo mile widziana aktualizacja! Dzięki!
Chris
Czy jest jakiś konkretny sposób, w jaki muszę to skonfigurować, dzwonię do następującego, let history = useHistory();ale Object is not callablepojawia się błąd, kiedy próbowałem zobaczyć, co to useHistory console.log(useHistory)to pokazuje się jako niezdefiniowane. using"react-router-dom": "^5.0.1"
steff_bdh
@steff_bdh musisz zaktualizować go w pliku yout package.json do „reag-router-dom”: „^ 5.0.1” i uruchomić „npm install”
Hadi Abu
2
Fajnie, ale nie można użyć haka wewnątrz klas akcji redux, ponieważ nie są one składnikiem / funkcją React
Jay
Jak wykorzystasz to do przekierowania przy logowaniu przy użyciu (asynchronizacji). Oto pytanie => stackoverflow.com/questions/62154408/…
theairbend3r
29

Najprostszym sposobem w React Router 4 jest użycie

this.props.history.push('/new/url');

Ale aby skorzystać z tej metody, istniejący komponent powinien mieć dostęp do historyobiektu. Możemy uzyskać dostęp przez

  1. Jeśli twój komponent jest Routebezpośrednio połączony, oznacza to , że ma on już dostęp do historyobiektu.

    na przykład:

    <Route path="/profile" component={ViewProfile}/>

    Tutaj ViewProfilema dostęp do history.

  2. Jeśli nie jest podłączony Routebezpośrednio.

    na przykład:

    <Route path="/users" render={() => <ViewUsers/>}

    Następnie musimy zastosować withRouterwyższą kolejność, aby wypaczać istniejący komponent.

    ViewUsersElement wewnętrzny

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

    • export default withRouter(ViewUsers);

    To wszystko, Twój ViewUserskomponent ma dostęp do historyobiektu.

AKTUALIZACJA

2- w tym scenariuszu przekaż całą trasę propsdo swojego komponentu, a następnie będziemy mogli uzyskać dostęp this.props.historyz komponentu nawet bezHOC

na przykład:

<Route path="/users" render={props => <ViewUsers {...props} />}
Saahithyan Vigneswaran
źródło
1
Świetny! Twoja druga metoda również this.props.historyzałatwiła sprawę , ponieważ mój komponent (który wymaga dostępu ) pochodzi z HOC, co oznacza, że ​​nie jest on bezpośrednio powiązany z Route, jak wyjaśniono.
cjauvin
25

Oto jak to zrobiłem:

import React, {Component} from 'react';

export default class Link extends Component {
    constructor(props) {
        super(props);
        this.onLogout = this.onLogout.bind(this);
    }
    onLogout() {
        this.props.history.push('/');
    }
    render() {
        return (
            <div>
                <h1>Your Links</h1>
                <button onClick={this.onLogout}>Logout</button>
            </div>
        );
    }
}

Skorzystaj this.props.history.push('/cart');z przekierowania do strony koszyka, która zostanie zapisana w obiekcie historii.

Ciesz się, Michael.

Michał Horojański
źródło
2
Tak, wygląda na to, że w komponentach można dobrze popchnąć. Jedynym sposobem wpłynięcia na nawigację poza komponentem jest przekierowanie.
Chris
14
To nie odpowiada na zadane pytanie, jak uzyskać dostęp do history.push OUTSIDE komponentu. Korzystanie z this.props.history nie jest opcją, gdy znajduje się poza komponentem.
SunshinyDoyle,
22

Zgodnie z dokumentacją React Router v4 - sesja głębokiej integracji Redux

Konieczna jest głęboka integracja, aby:

„być w stanie nawigować poprzez wysyłanie akcji”

Zalecają jednak to podejście jako alternatywę dla „głębokiej integracji”:

„Zamiast wywoływać akcje nawigacyjne, możesz przekazać udostępniony obiekt historii, aby skierować komponenty do swoich akcji i nawigować tam.”

Możesz więc owinąć swój komponent za pomocą komponentu withRouter:

export default withRouter(connect(null, { actionCreatorName })(ReactComponent));

który przekaże interfejs API historii do rekwizytów. Możesz więc zadzwonić do twórcy akcji, który przekazuje historię jako param. Na przykład wewnątrz ReactComponent:

onClick={() => {
  this.props.actionCreatorName(
    this.props.history,
    otherParams
  );
}}

Następnie wewnątrz akcji / index.js:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}
alainbex
źródło
19

Paskudne pytanie zajęło mi sporo czasu, ale ostatecznie rozwiązałem to w ten sposób:

Zawiń swój kontener withRouteri przekaż historię swojej akcji w mapDispatchToPropsfunkcji. W akcji nawiguj za pomocą history.push ('/ url').

Akcja:

export function saveData(history, data) {
  fetch.post('/save', data)
     .then((response) => {
       ...
       history.push('/url');
     })
};

Pojemnik:

import { withRouter } from 'react-router-dom';
...
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    save: (data) => dispatch(saveData(ownProps.history, data))}
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));

Jest to ważne dla React Router v4.x .

Khrystyna Skvarok
źródło
Dzięki, twoje rozwiązanie withRouter działa na maszynie do pisania, ale jest dość wolne w porównaniu z wcześniejszym import { createBrowserHistory } from 'history' pomysłem, proszę?
Jay
7

this.context.history.push nie będzie działać.

Udało mi się uzyskać push działający w następujący sposób:

static contextTypes = {
    router: PropTypes.object
}

handleSubmit(e) {
    e.preventDefault();

    if (this.props.auth.success) {
        this.context.router.history.push("/some/Path")
    }

}
Aimar
źródło
9
To nie odpowiada na zadane pytanie, jak uzyskać dostęp do history.push OUTSIDE komponentu. Korzystanie z this.context nie jest opcją, gdy znajduje się poza komponentem.
SunshinyDoyle,
6

W tym przypadku przekazujesz rekwizyty swojemu thunkowi. Możesz więc po prostu zadzwonić

props.history.push('/cart')

Jeśli tak nie jest, nadal możesz przekazać historię ze swojego komponentu

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}
użytkownik3812377
źródło
6

Oferuję jeszcze jedno rozwiązanie na wypadek, gdyby było to dla kogoś warte.

Mam history.jsplik, w którym mam następujące elementy:

import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history

Następnie w moim katalogu głównym, w którym definiuję router, używam:

import history from '../history'
import { Provider } from 'react-redux'
import { Router, Route, Switch } from 'react-router-dom'

export default class Root extends React.Component {
  render() {
    return (
     <Provider store={store}>
      <Router history={history}>
       <Switch>
        ...
       </Switch>
      </Router>
     </Provider>
    )
   }
  }

Na koniec actions.jsimportuję Historię i korzystam z pushLater

import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)

W ten sposób mogę wywoływać nowe działania po wywołaniach API.

Mam nadzieję, że to pomoże!

Diego
źródło
4

Jeśli używasz Redux, to polecam użycie pakietu npm reaguj-router-redux . Umożliwia wysyłanie akcji nawigacyjnych sklepu Redux.

Musisz utworzyć sklep zgodnie z opisem w pliku Readme .

Najłatwiejszy przypadek użycia:

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

this.props.dispatch(push('/second page'));

Drugi przypadek użycia z pojemnikiem / komponentem:

Pojemnik:

import { connect } from 'react-redux';
import { push } from 'react-router-redux';

import Form from '../components/Form';

const mapDispatchToProps = dispatch => ({
  changeUrl: url => dispatch(push(url)),
});

export default connect(null, mapDispatchToProps)(Form);

Składnik:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class Form extends Component {
  handleClick = () => {
    this.props.changeUrl('/secondPage');
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}/>
      </div>Readme file
    );
  }
}
czarny
źródło
1
To nie działa z React-Router-Redux, chyba że używasz nextwersji, która jest wciąż w fazie rozwoju!
froginvasion
4

Udało mi się to osiągnąć za pomocą bind(). Chciałem kliknąć przycisk index.jsx, opublikować dane na serwerze, ocenić odpowiedź i przekierować na success.jsx. Oto jak to wypracowałem ...

index.jsx:

import React, { Component } from "react"
import { postData } from "../../scripts/request"

class Main extends Component {
    constructor(props) {
        super(props)
        this.handleClick = this.handleClick.bind(this)
        this.postData = postData.bind(this)
    }

    handleClick() {
        const data = {
            "first_name": "Test",
            "last_name": "Guy",
            "email": "[email protected]"
        }

        this.postData("person", data)
    }

    render() {
        return (
            <div className="Main">
                <button onClick={this.handleClick}>Test Post</button>
            </div>
        )
    }
}

export default Main

request.js:

import { post } from "./fetch"

export const postData = function(url, data) {
    // post is a fetch() in another script...
    post(url, data)
        .then((result) => {
            if (result.status === "ok") {
                this.props.history.push("/success")
            }
        })
}

success.jsx:

import React from "react"

const Success = () => {
    return (
        <div className="Success">
            Hey cool, got it.
        </div>
    )
}

export default Success

Więc łącząc się thisz postDatain index.jsx, mogłem uzyskać dostęp this.props.historydo request.js... wtedy mogę ponownie użyć tej funkcji w różnych komponentach, po prostu upewnij się, że pamiętam o dołączeniu this.postData = postData.bind(this)do constructor().

skwidbreth
źródło
3

Oto mój hack (to jest mój plik na poziomie root, z dodanym trochę redux - choć nie używam react-router-redux):

const store = configureStore()
const customHistory = createBrowserHistory({
  basename: config.urlBasename || ''
})

ReactDOM.render(
  <Provider store={store}>
    <Router history={customHistory}>
      <Route component={({history}) => {
        window.appHistory = history
        return (
          <App />
        )
      }}/>
    </Router>
  </Provider>,
  document.getElementById('root')
)

Mogę wtedy używać window.appHistory.push()gdziekolwiek chcę (na przykład w moich funkcjach sklepu redux / thunks / sagas itp.) Miałem nadzieję, że mogę po prostu użyć, window.customHistory.push()ale z jakiegoś powodu react-routernigdy nie wydawałem się aktualizować, nawet jeśli zmieniłem adres URL. Ale w ten sposób korzystam z instancji EXACT react-router. Nie uwielbiam umieszczać rzeczy w zasięgu globalnym i jest to jedna z niewielu rzeczy, które bym to zrobił. Ale to lepsze niż jakakolwiek inna alternatywa, jaką widziałem w IMO.

Joao
źródło
3

Użyj oddzwaniania. To zadziałało dla mnie!

export function addProduct(props, callback) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
    .then(response => {
    dispatch({ type: types.AUTH_USER });
    localStorage.setItem('token', response.data.token);
    callback();
  });
}

W komponencie wystarczy dodać oddzwonienie

this.props.addProduct(props, () => this.props.history.push('/cart'))
Priyansh Rastogi
źródło
3

więc tak to robię: - zamiast przekierowywania za pomocą history.push, po prostu używam Redirectkomponentu z react-router-dom Podczas korzystania z tego komponentu możesz po prostu przekazać push=true, a zajmie się resztą

import * as React from 'react';
import { Redirect } from 'react-router-dom';
class Example extends React.Component {
  componentDidMount() {
    this.setState({
      redirectTo: '/test/path'
    });
  }

  render() {
    const { redirectTo } = this.state;

    return <Redirect to={{pathname: redirectTo}} push={true}/>
  }
}
LuizAsFight
źródło
jest to poprawne, które nie przerywa cyklu renderowania
jzqa
1

Router React V4 pozwala teraz na użycie rekwizytu historii w następujący sposób:

this.props.history.push("/dummy",value)

Dostęp do tej wartości można uzyskać wszędzie tam, gdzie prop położenie jest dostępny jako state:{value}stan inny niż komponent.

Snivio
źródło
1
To nie odpowiada na zadane pytanie, jak uzyskać dostęp do history.push OUTSIDE komponentu. Korzystanie z this.props.history nie jest opcją, gdy znajduje się poza komponentem.
Arkady
0

możesz użyć tego w ten sposób, ponieważ robię to do logowania i wiele innych rzeczy

class Login extends Component {
  constructor(props){
    super(props);
    this.login=this.login.bind(this)
  }


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


render() {

    return (

   <div>
    <button onClick={this.login}>login</login>
    </div>

)
jadlmir
źródło
0
/*Step 1*/
myFunction(){  this.props.history.push("/home"); }
/**/
 <button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go 
 Home</button>
David Bagdasaryan
źródło
Nie ma potrzeby importowania!
David Bagdasaryan,
1
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, dlaczego i / lub jak ten kod odpowiada na pytanie, poprawia jego długoterminową wartość.
rollstuhlfahrer
0

krok pierwszy zawiń aplikację w Router

import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));

Teraz moja cała aplikacja będzie miała dostęp do BrowserRouter. Krok drugi Importuję trasę, a następnie przekazuję te rekwizyty. Prawdopodobnie w jednym z twoich głównych plików.

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

//lots of code here

//somewhere in my render function

    <Route
      exact
      path="/" //put what your file path is here
      render={props => (
      <div>
        <NameOfComponent
          {...props} //this will pass down your match, history, location objects
        />
      </div>
      )}
    />

Teraz, jeśli uruchomię plik console.log (this.props) w pliku js komponentu, powinienem otrzymać coś, co wygląda tak

{match: {…}, location: {…}, history: {…}, //other stuff }

Krok 2 Mogę uzyskać dostęp do obiektu historii, aby zmienić moją lokalizację

//lots of code here relating to my whatever request I just ran delete, put so on

this.props.history.push("/") // then put in whatever url you want to go to

Jestem także studentem kodowania bootcamp, więc nie jestem ekspertem, ale wiem, że możesz także użyć

window.location = "/" //wherever you want to go

Popraw mnie, jeśli się mylę, ale kiedy to przetestowałem, przeładowało całą stronę, co, jak sądzę, pokonało cały sens używania React.


źródło
0

Utwórz niestandardowy Routerwłasny browserHistory:

import React from 'react';
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';

export const history = createBrowserHistory();

const ExtBrowserRouter = ({children}) => (
  <Router history={history} >
  { children }
  </Router>
);

export default ExtBrowserRouter

Następnie w Routerkatalogu głównym , w którym zdefiniujesz swój , użyj następujących poleceń:

import React from 'react';       
import { /*BrowserRouter,*/ Route, Switch, Redirect } from 'react-router-dom';

//Use 'ExtBrowserRouter' instead of 'BrowserRouter'
import ExtBrowserRouter from './ExtBrowserRouter'; 
...

export default class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <ExtBrowserRouter>
          <Switch>
            ...
            <Route path="/login" component={Login}  />
            ...
          </Switch>
        </ExtBrowserRouter>
      </Provider>
    )
  }
}

Na koniec zaimportuj historytam, gdzie jest to potrzebne i użyj:

import { history } from '../routers/ExtBrowserRouter';
...

export function logout(){
  clearTokens();      
  history.push('/login'); //WORKS AS EXPECTED!
  return Promise.reject('Refresh token has expired');
}
Nolesh
źródło
0

Jeśli chcesz użyć historii podczas przekazywania funkcji jako wartości do rekwizytu komponentu, za pomocą routera reagującego 4 możesz po prostu zniszczyć historyrekwizyt w atrybucie renderowania <Route/>komponentu, a następnie użyćhistory.push()

    <Route path='/create' render={({history}) => (
      <YourComponent
        YourProp={() => {
          this.YourClassMethod()
          history.push('/')
        }}>
      </YourComponent>
    )} />

Uwaga: Aby to zadziałało, należy owinąć komponent React Router BrowserRouter wokół głównego komponentu (np. Który może znajdować się w pliku index.js)

Kewal Shah
źródło