Bagaimana cara mendorong ke History di React Router v4?

361

Dalam versi React Router (v3) saat ini, saya dapat menerima respons server dan gunakan browserHistory.pushuntuk membuka halaman respons yang sesuai. Namun, ini tidak tersedia di v4, dan saya tidak yakin apa cara yang tepat untuk menangani ini.

Dalam contoh ini, menggunakan Redux, komponen / app-product-form.js panggilan this.props.addProduct(props)saat pengguna mengirimkan formulir. Ketika server mengembalikan sukses, pengguna dibawa ke halaman Cart.

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

Bagaimana saya bisa membuat redirect ke halaman Cart dari fungsi untuk React Router v4?

Chris
sumber
Hanya untuk menambahkan ini dari solusi terakhir yang ditawarkan dan dari saran dalam masalah React Router di GitHub, menggunakan contextuntuk melewati apa yang Anda butuhkan secara manual adalah "no go". Kecuali saya seorang penulis perpustakaan, seharusnya tidak perlu menggunakannya. Bahkan, Facebook merekomendasikan untuk tidak melakukannya.
Chris
@ Chris apakah Anda menemukan solusi untuk ini? saya perlu mendorong ke komponen yang berbeda dalam aksi, sama seperti yang telah Anda jelaskan di sini
Mr.G
@ Mr.G, sayangnya saya belum. Terakhir saya baca adalah tim Pelatihan React yang memelihara React Router memiliki paket redux yang tersedia. Saya belum beruntung membuatnya berhasil, dan mereka belum berusaha keras untuk menyelesaikannya.
Chris
Mengapa kita tidak bisa menggunakan windows.location.href = URL? Apakah ada yang salah dalam menggunakannya untuk mengubah URL dan mengarahkan ulang?
Shan
Saya tidak mengerti mengapa tidak, tetapi opsi untuk menggunakan historyjuga berfungsi untuk React Native sebagai opsi dan juga opsi tambahan untuk mendukung browser lawas.
Chris

Jawaban:

308

Anda dapat menggunakan historymetode di luar komponen Anda. Coba dengan cara berikut.

Pertama, buat historyobjek menggunakan paket histori :

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

Kemudian bungkus <Router>( harap dicatat , Anda harus menggunakannya import { Router }sebagai gantinya 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'),
);

Ubah lokasi Anda saat ini dari tempat mana pun, misalnya:

// src/actions/userActionCreators.js

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

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

UPD : Anda juga dapat melihat contoh yang sedikit berbeda di React Router FAQ .

Oleg Belostotsky
sumber
24
Saya telah mencoba melakukan persis seperti yang dikatakan @OlegBelostotsky, tetapi setelah itu history.push('some path'), URL berubah tetapi halaman tidak berubah. Saya harus meletakkannya window.location.reload()di beberapa bagian kode saya hanya untuk membuatnya bekerja. Namun, dalam satu contoh saya harus menyimpan pohon redux state, dan memuat ulang menghancurkannya. Ada solusi lain?
sdabrutas
2
@ idunno Coba gunakan komponen withRoutertingkat tinggi.
Oleg Belostotsky
Ini melempar saya kesalahan yang menyatakan: createBrowserHistory bukan fungsi. Apa yang dapat saya?
AKJ
@ AKJ Mungkin import createHistory from 'history/createBrowserHistory'; export default createHistory();akan berhasil.
Oleg Belostotsky
1
Maaf untuk downvote :). Meskipun ini juga harus bekerja, cara yang benar untuk menangani ini adalah bagaimana Chris menjawab: stackoverflow.com/a/42716055/491075 .
gion_13
340

React Router v4 pada dasarnya berbeda dari v3 (dan sebelumnya) dan Anda tidak dapat melakukan browserHistory.push()seperti dulu.

Diskusi ini tampaknya terkait jika Anda ingin info lebih lanjut:

  • Membuat yang baru browserHistorytidak akan berhasil karena <BrowserRouter>membuat instance riwayatnya sendiri, dan mendengarkan perubahannya. Jadi contoh yang berbeda akan mengubah url tetapi tidak memperbarui <BrowserRouter>.
  • browserHistory tidak terpapar oleh react-router di v4, hanya di v2.

Alih-alih, Anda memiliki beberapa opsi untuk melakukan ini:

  • Gunakan komponen withRoutertingkat tinggi

    Alih-alih, Anda harus menggunakan withRouterkomponen pesanan tinggi, dan membungkusnya dengan komponen yang akan mendorong ke sejarah. Sebagai contoh:

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

    Lihat dokumentasi resmi untuk info lebih lanjut:

    Anda bisa mendapatkan akses ke historyproperti obyek dan yang paling dekat <Route>'s matchmelalui withRouter komponen tingkat tinggi. withRouter akan membuat ulang komponen setiap kali rute perubahan dengan alat peraga yang sama seperti <Route>membuat alat peraga: { match, location, history }.


  • Gunakan contextAPI

    Menggunakan konteks mungkin merupakan salah satu solusi termudah, tetapi karena API eksperimental itu tidak stabil dan tidak didukung. Gunakan hanya ketika semuanya gagal. Ini sebuah contoh:

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

    Lihat dokumentasi resmi tentang konteks:

    Jika Anda ingin aplikasi Anda stabil, jangan gunakan konteks. Ini adalah API eksperimental dan kemungkinan akan pecah dalam rilis React di masa depan.

    Jika Anda bersikeras menggunakan konteks meskipun ada peringatan ini, cobalah untuk mengisolasi penggunaan konteks Anda ke area kecil dan hindari menggunakan API konteks secara langsung jika memungkinkan sehingga lebih mudah untuk memutakhirkan ketika API berubah.

Chris
sumber
9
Ya saya memang mencobanya. Terima kasih untuk bertanya. :-) Jadi bagaimana Anda mendapatkan konteks ke dalam fungsi aksi ini? Sejauh ini, itu muncul sebagai tidak terdefinisi.
Chris
1
Saya telah meneliti topik ini selama beberapa hari sekarang dan belum bisa membuatnya bekerja. Bahkan dengan menggunakan contoh di atas saya tetap mendapatkan router tidak ditentukan dalam konteksnya. Saat ini saya menggunakan react v15.5.10, react-router-dom v4.1.1, prop-types 15.5.10. Dokumentasi tentang ini jarang dan tidak terlalu jelas.
Stu
5
@Stu ini harus bekerjathis.context.router.history.push('/path');
Tushar Khatiwada
1
@ Chris Memang, jika Anda mencoba untuk instantiate objek sejarah dan menggunakannya sendiri akan mengubah url tetapi tidak akan membuat komponen - seperti yang Anda sebutkan di atas. Tapi, bagaimana cara menggunakan "history.push" di luar komponen dan memaksa komponen render juga?
keren
52
Ini tidak menjawab pertanyaan yang diajukan yaitu bagaimana cara mengakses history.push OUTSIDE komponen. Menggunakan withRouter atau konteksnya bukanlah opsi untuk saat berada di luar komponen.
SunshinyDoyle
49

Sekarang dengan react-router v5 Anda dapat menggunakan hook siklus hidup useHistory seperti ini:

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

baca lebih lanjut di: https://reacttraining.com/react-router/web/api/Hooks/usehistory

Hadi Abu
sumber
1
Itu pembaruan yang sangat disambut baik! Terima kasih!
Chris
Apakah ada cara khusus yang saya perlukan untuk mengatur ini, saya memanggil yang berikut let history = useHistory();tetapi mendapatkan Object is not callablekesalahan, ketika saya mencoba melihat apa yang digunakan oleh Histori, apakah console.log(useHistory)itu ditampilkan sebagai tidak terdefinisi. menggunakan"react-router-dom": "^5.0.1"
steff_bdh
@steff_bdh Anda perlu memperbaruinya dalam file package.json Anda ke "react-router-dom": "^ 5.0.1" dan jalankan 'npm install'
Hadi Abu
2
Bagus, tetapi tidak dapat menggunakan hook di dalam kelas aksi redux karena mereka tidak Bereaksi komponen / fungsi
Jay
Bagaimana Anda menggunakan ini untuk pengalihan setelah menggunakan login (async). Inilah pertanyaan => stackoverflow.com/questions/62154408/…
theairbend3r
29

Cara paling sederhana dalam React Router 4 adalah menggunakan

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

Tetapi untuk menggunakan metode ini, komponen Anda yang ada harus memiliki akses ke historyobjek. Kami bisa mendapatkan akses dengan

  1. Jika komponen Anda terhubung Routesecara langsung, maka komponen Anda sudah memiliki akses ke historyobjek.

    misalnya:

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

    Di sini ViewProfilememiliki akses ke history.

  2. Jika tidak terhubung Routelangsung.

    misalnya:

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

    Maka kita harus menggunakan withRouter, perintah yang lebih tinggi untuk melengkungkan komponen yang ada.

    ViewUsersKomponen di dalam

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

    • export default withRouter(ViewUsers);

    Itu saja sekarang, ViewUserskomponen Anda memiliki akses ke historyobjek.

MEMPERBARUI

2- dalam skenario ini, lewati semua rute propske komponen Anda, dan kemudian kita dapat mengakses this.props.historydari komponen bahkan tanpa aHOC

misalnya:

<Route path="/users" render={props => <ViewUsers {...props} />}
Saahithyan Vigneswaran
sumber
1
Luar biasa! Metode kedua Anda juga melakukan trik untuk saya, karena komponen saya (yang membutuhkan akses ke this.props.history) berasal dari HOC, yang berarti bahwa itu tidak terkait langsung dengan Route, seperti yang Anda jelaskan.
cjauvin
25

Beginilah cara saya melakukannya:

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

Gunakan this.props.history.push('/cart');untuk mengarahkan ke halaman keranjang itu akan disimpan di objek sejarah.

Selamat menikmati, Michael.

Michael Horojanski
sumber
2
Ya, sepertinya di dalam komponen Anda bisa mendorong dengan baik. Satu-satunya cara untuk mempengaruhi navigasi di luar komponen adalah dengan redirect.
Chris
14
Ini tidak menjawab pertanyaan yang diajukan yaitu bagaimana cara mengakses history.push OUTSIDE komponen. Menggunakan this.props.history bukan opsi untuk saat di luar komponen.
SunshinyDoyle
22

Menurut dokumentasi React Router v4 - sesi Redux Deep Integration

Diperlukan integrasi yang dalam untuk:

"dapat menavigasi dengan mengirimkan tindakan"

Namun, mereka merekomendasikan pendekatan ini sebagai alternatif untuk "integrasi mendalam":

"Daripada mengirim tindakan untuk bernavigasi, Anda dapat melewati objek riwayat yang disediakan untuk merutekan komponen ke tindakan Anda dan menavigasi dengan itu di sana."

Jadi, Anda dapat membungkus komponen Anda dengan komponen pesanan tinggi withRouter:

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

yang akan meneruskan API riwayat ke alat peraga. Jadi, Anda dapat memanggil pencipta aksi yang meneruskan sejarah sebagai param. Misalnya, di dalam ReactComponent Anda:

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

Lalu, di dalam action / index.js Anda:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}
alainbex
sumber
19

Pertanyaan jahat, butuh waktu cukup lama, tetapi akhirnya, saya menyelesaikannya dengan cara ini:

Bungkus wadah Anda dengan withRouterdan sampaikan riwayat ke tindakan Anda dalam mapDispatchToPropsfungsi. Dalam aksi gunakan history.push ('/ url') untuk bernavigasi.

Tindakan:

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

Wadah:

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

Ini berlaku untuk Bereaksi Router v4.x .

Khrystyna Skvarok
sumber
Terima kasih, solusi withRouter Anda bekerja dengan naskah tetapi cukup lambat dibandingkan dengan sebelumnya import { createBrowserHistory } from 'history' ada ide tolong?
Jay
7

this.context.history.push tidak akan bekerja.

Saya berhasil mendapatkan kerja dorong seperti ini:

static contextTypes = {
    router: PropTypes.object
}

handleSubmit(e) {
    e.preventDefault();

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

}
Aimar
sumber
9
Ini tidak menjawab pertanyaan yang diajukan yaitu bagaimana cara mengakses history.push OUTSIDE komponen. Menggunakan this.context bukan pilihan ketika berada di luar komponen.
SunshinyDoyle
6

Dalam hal ini Anda memberikan properti ke thunk Anda. Jadi, Anda cukup menelepon

props.history.push('/cart')

Jika ini tidak terjadi, Anda masih dapat meneruskan riwayat dari komponen Anda

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}
pengguna3812377
sumber
6

Saya menawarkan satu solusi lagi jika itu bermanfaat untuk orang lain.

Saya memiliki history.jsfile di mana saya memiliki yang berikut ini:

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

Selanjutnya, pada Root saya di mana saya mendefinisikan router saya, saya menggunakan yang berikut ini:

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

Akhirnya, pada saya actions.jsmengimpor History dan memanfaatkan pushLater

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

Dengan cara ini, saya dapat mendorong ke tindakan baru setelah panggilan API.

Semoga ini bisa membantu!

Diego
sumber
4

Jika Anda menggunakan Redux, maka saya akan merekomendasikan menggunakan paket npm react-router-redux . Ini memungkinkan Anda untuk mengirim tindakan navigasi toko Redux.

Anda harus membuat toko seperti yang dijelaskan dalam file Readme mereka .

Kasing penggunaan termudah:

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

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

Kasus penggunaan kedua dengan Wadah / Komponen:

Wadah:

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

Komponen:

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
    );
  }
}
Hitam
sumber
1
Ini tidak bekerja dengan react-router-redux kecuali Anda menggunakan nextversi yang masih dalam pengembangan saat ini!
froginvasion
4

Saya bisa mencapai ini dengan menggunakan bind(). Saya ingin mengklik tombol di index.jsx, memposting beberapa data ke server, mengevaluasi respons, dan mengarahkan ke success.jsx. Begini cara saya mengatasinya ...

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

Jadi dengan mengikat thiske postDatadalam index.jsx, saya bisa akses this.props.historydi request.js... maka saya bisa menggunakan kembali fungsi ini dalam komponen yang berbeda, hanya untuk memastikan aku ingat untuk menyertakan this.postData = postData.bind(this)dalam constructor().

skwidbreth
sumber
3

Inilah hack saya (ini adalah file level root saya, dengan sedikit redux yang tercampur di sana - meskipun saya tidak menggunakan 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')
)

Saya kemudian dapat menggunakan di window.appHistory.push()mana saja saya inginkan (misalnya, di fungsi toko redux saya / thunks / sagas, dll) saya berharap saya hanya bisa menggunakan window.customHistory.push()tetapi untuk beberapa alasan react-routersepertinya tidak pernah memperbarui meskipun url berubah. Tapi dengan cara ini saya react-routermenggunakan instance EXACT . Saya tidak suka meletakkan barang-barang di lingkup global, dan ini adalah salah satu dari beberapa hal yang saya lakukan dengan itu. Tapi ini lebih baik daripada alternatif lain yang pernah saya lihat IMO.

Joao
sumber
3

Gunakan Callback. Itu berhasil untuk saya!

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

Dalam komponen, Anda hanya perlu menambahkan callback

this.props.addProduct(props, () => this.props.history.push('/cart'))
Priyansh Rastogi
sumber
3

jadi cara saya melakukannya adalah: - Alih-alih mengarahkan ulang menggunakan history.push, saya hanya menggunakan Redirectkomponen dari react-router-dom Ketika menggunakan komponen ini Anda hanya dapat lulus push=true, dan itu akan mengurus sisanya

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
sumber
ini adalah benar yang tidak merusak siklus render reaksi
jzqa
1

React router V4 sekarang memungkinkan prop sejarah untuk digunakan seperti di bawah ini:

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

Nilai tersebut kemudian dapat diakses di mana pun prop lokasi tersedia sebagai state:{value}bukan komponen.

Snivio
sumber
1
Ini tidak menjawab pertanyaan yang diajukan yaitu bagaimana cara mengakses history.push OUTSIDE komponen. Menggunakan this.props.history bukan opsi untuk saat di luar komponen.
Arkady
0

Anda dapat menggunakannya seperti ini karena saya melakukannya untuk login dan manny hal yang berbeda

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
sumber
0
/*Step 1*/
myFunction(){  this.props.history.push("/home"); }
/**/
 <button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go 
 Home</button>
David Bagdasaryan
sumber
Tidak perlu impor!
David Bagdasaryan
1
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
rollstuhlfahrer
0

langkah pertama bungkus aplikasi Anda di Router

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

Sekarang seluruh Aplikasi saya akan memiliki akses ke BrowserRouter. Langkah kedua saya mengimpor Rute dan kemudian menurunkan alat peraga itu. Mungkin di salah satu file utama Anda.

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

Sekarang jika saya menjalankan console.log (this.props) di file js komponen saya bahwa saya harus mendapatkan sesuatu yang terlihat seperti ini

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

Langkah 2 Saya dapat mengakses objek riwayat untuk mengubah lokasi saya

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

Saya juga hanya seorang mahasiswa coding bootcamp, jadi saya bukan ahli, tapi saya tahu Anda juga bisa menggunakannya

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

Koreksi saya jika saya salah, tetapi ketika saya mengujinya itu memuat ulang seluruh halaman yang saya pikir mengalahkan seluruh titik menggunakan Bereaksi.


sumber
0

Buat custom Routerdengan sendiri 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

Selanjutnya, pada Root Anda di mana Anda mendefinisikan Anda Router, gunakan yang berikut:

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

Terakhir, impor di historymana Anda membutuhkannya dan gunakan:

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

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

Jika Anda ingin menggunakan histori sambil meneruskan fungsi sebagai nilai ke prop Component, dengan react-router 4 Anda bisa menghancurkan struktur historyprop dalam atribut render dari <Route/>Component dan kemudian menggunakanhistory.push()

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

Catatan: Agar ini berfungsi, Anda harus membungkus Komponen BrowserRouter React Router di sekitar komponen root Anda (mis. Yang mungkin ada di index.js)

Kewal Shah
sumber