react-router kembali ke halaman bagaimana Anda mengkonfigurasi sejarah?


123

Adakah yang bisa memberi tahu saya bagaimana saya bisa kembali ke halaman sebelumnya daripada rute tertentu?

Saat menggunakan kode ini:

var BackButton = React.createClass({

 mixins: [Router.Navigation],
  render: function() {
    return (
        <button
            className="button icon-left"
            onClick={this.navigateBack}>
            Back
        </button>
    );
  },

  navigateBack: function(){
    this.goBack();
  }
});

Dapatkan kesalahan ini, goBack () diabaikan karena tidak ada riwayat router

Inilah rute saya:

// Routing Components
Route = Router.Route;
RouteHandler = Router.RouteHandler;
DefaultRoute = Router.DefaultRoute;

var routes = (
 <Route name="app" path="/" handler={OurSchoolsApp}>
     <DefaultRoute name="home" handler={HomePage} />
     <Route name="add-school" handler={AddSchoolPage}  />
     <Route name="calendar" handler={CalendarPage}  />
     <Route name="calendar-detail" path="calendar-detail/:id" handler={CalendarDetailPage} />
     <Route name="info-detail" path="info-detail/:id" handler={InfoDetailPage} />
     <Route name="info" handler={InfoPage} />
     <Route name="news" handler={NewsListPage} />
     <Route name="news-detail" path="news-detail/:id" handler={NewsDetailPage} />
     <Route name="contacts" handler={ContactPage} />
     <Route name="contact-detail" handler={ContactDetailPage} />
     <Route name="settings" handler={SettingsPage} />
 </Route>
 );

 Router.run(routes, function(Handler){
   var mountNode = document.getElementById('app');
   React.render(<Handler /> , mountNode);
 });

Jika Anda telah menemukan solusi, bisakah Anda berbagi di sini. Terima kasih.
pengguna261002

Jawaban:


44

Saya pikir Anda hanya perlu mengaktifkan BrowserHistory pada router Anda dengan intializing seperti itu: <Router history={new BrowserHistory}>.

Sebelum itu, Anda harus meminta BrowserHistorydari'react-router/lib/BrowserHistory'

Saya harap itu membantu !

UPDATE: contoh di ES6

const BrowserHistory = require('react-router/lib/BrowserHistory').default;

const App = React.createClass({
    render: () => {
        return (
            <div><button onClick={BrowserHistory.goBack}>Go Back</button></div>
        );
    }
});

React.render((
    <Router history={BrowserHistory}>
        <Route path="/" component={App} />
    </Router>
), document.body);

hai, kami menghadapi masalah yang sama. bisakah Anda menjelaskan lebih detail. TERIMA KASIH
pengguna261002

23
Bagaimana ini jawaban yang benar? Ini bahkan tidak menjawab pertanyaan itu. @bomber
GN.

15
Untuk siapa saja yang membaca ini. Jika Anda ingin melakukan ini dari komponen anak. Anda dapat menemukan objek sejarah di this.props.history. Jadi, kodenya menjadithis.props.history.goBack
Sisir

3
Bagaimana dengan react-router 4? Saya tidak berpikir itu mendukung BrowserHistory lagi.
Akshay Lokur

1
Pada react-router-dom versi 5, sejarah dibuat oleh BrowserRouter secara implisit dan tersedia melalui props, Anda dapat mengaksesnya melalui props.history.
Srikanth Kyatham

98

Perbarui dengan React v16 dan ReactRouter v4.2.0 (Oktober 2017):

class BackButton extends Component {
  static contextTypes = {
    router: () => true, // replace with PropTypes.object if you use them
  }

  render() {
    return (
      <button
        className="button icon-left"
        onClick={this.context.router.history.goBack}>
          Back
      </button>
    )
  }
}

Pembaruan dengan React v15 dan ReactRouter v3.0.0 (Agustus 2016):

var browserHistory = ReactRouter.browserHistory;

var BackButton = React.createClass({
  render: function() {
    return (
      <button
        className="button icon-left"
        onClick={browserHistory.goBack}>
        Back
      </button>
    );
  }
});

Membuat biola dengan contoh yang sedikit lebih kompleks dengan iframe tertanam: https://jsfiddle.net/kwg1da3a/

React v14 dan ReacRouter v1.0.0 (10 Sep 2015)

Kamu bisa melakukan ini:

var React = require("react");
var Router = require("react-router");

var SomePage = React.createClass({
  ...

  contextTypes: {
    router: React.PropTypes.func
  },
  ...

  handleClose: function () {
    if (Router.History.length > 1) {
      // this will take you back if there is history
      Router.History.back();
    } else {
      // this will take you to the parent route if there is no history,
      // but unfortunately also add it as a new route
      var currentRoutes = this.context.router.getCurrentRoutes();
      var routeName = currentRoutes[currentRoutes.length - 2].name;
      this.context.router.transitionTo(routeName);
    }
  },
  ...

Anda harus berhati-hati karena Anda memiliki riwayat yang diperlukan untuk kembali. Jika Anda menekan halaman secara langsung dan kemudian menekannya kembali, itu akan membawa Anda kembali ke riwayat browser sebelum aplikasi Anda.

Solusi ini akan menangani kedua skenario tersebut. Namun, ini tidak akan menangani iframe yang dapat bernavigasi di dalam halaman (dan menambah riwayat browser), dengan tombol kembali. Terus terang, saya pikir itu adalah bug di react-router. Masalah dibuat di sini: https://github.com/rackt/react-router/issues/1874


Alangkah baiknya jika ada cara untuk melakukan ini tanpa menggunakan konteks?
Adam D

1
Juga, bergantung pada penyiapan, mungkin menggunakan this.props.history.goBack daripada this.context.router.history.goBack
PhoenixB

54
  1. impor withRouter

    import { withRouter } from 'react-router-dom';
  2. Ekspor komponen Anda sebagai:

    export withRouter(nameofcomponent) 
  3. Contoh, saat mengklik tombol, panggil goBack:

    <button onClick={this.props.history.goBack}>Back</button>

Diuji di react-router-domv4.3


2
BTW berfungsi untuk saya bahkan tanpa mengimpor atau menggunakan withRouter. Mungkin kami hanya menggunakan API asli riwayat browser. Tapi apakah itu oke ??
Gianfranco P.

1
Itu solusi yang bagus. Satu-satunya masalah ketika pengguna membuka halaman menggunakan URL langsung -> itu akan merusak aplikasi karena tidak memiliki riwayat.
skryvets

2
Penjelasan terbaik di sini
Z_z_Z

@MichaelFreidgeim dapatkah Anda mengunggah cuplikan kode Anda sehingga saya akan memeriksa dan memverifikasi
gaurav makwana

43
this.context.router.goBack()

Tidak perlu mixin navigasi!


1
Ini masih berfungsi di React Router v4, tetapi ini this.context.router.history.goBack. (+ sejarah)
Ben Gotow

13
Dengan react-router-dom: "v4.2.2" dan import { withRouter } from 'react-router-dom';berfungsi denganthis.props.history.goBack();
felansu

1
Selain komentar @ felansu, Anda juga perlu mengekspor komponen Anda denganRouter seperti yang dijelaskan dalam jawaban stackoverflow.com/a/49130220/3123338
Tuan Q

32

Metode ES6 tanpa mixin menggunakan react-router, fungsi stateless.

import React from 'react'
import { browserHistory } from 'react-router'

export const Test = () => (
  <div className="">
    <button onClick={browserHistory.goBack}>Back</button>
  </div>
)

3
Saya mendapatkan peringatan browser saat mencoba solusi Anda:export 'browserHistory' was not found in 'react-router'
Ralph David Abernathy

2
browserHistory hanya ada di v2 dan v3. Jika Anda menggunakan v4, Anda harus membaca panduan migrasi: github.com/ReactTraining/react-router/blob/…
ptorsson

@Ralp, jika Anda mendapatkan pesan kesalahan ini, periksa ini: stackoverflow.com/questions/49787659/…
Miles M.

13

Menggunakan React Hooks

Impor:

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

Dalam komponen stateless:

  let history = useHistory();

Pada Acara

history.goBack()

<button onClick = {() => history.goBack ()}> Kembali </button>
Hunter

Terima kasih telah menyebutkan ini karena saya suka pengait. Saya telah menggunakan withRouter sejauh ini.
Newman

10

Lihat contoh kerja saya menggunakan React 16.0 dengan Contoh React-router v4 Live . lihat kode Github

Gunakan withRouterdanhistory.goBack()

Ini adalah ide yang saya terapkan ...

History.js

import React, { Component } from 'react';
import { withRouter } from 'react-router-dom'
import './App.css'


class History extends Component {

  handleBack = () => {
    this.props.history.goBack()
  }

  handleForward = () => {
    console.log(this.props.history)
    this.props.history.go(+1)
  }

  render() {
    return <div className="container">
      <div className="row d-flex justify-content-between">
        <span onClick={this.handleBack} className="d-flex justify-content-start button">
          <i className="fas fa-arrow-alt-circle-left fa-5x"></i>
        </span>
        <span onClick={this.handleForward} className="d-flex justify-content-end button">
          <i className="fas fa-arrow-alt-circle-right fa-5x"></i>
        </span>
      </div>
    </div>
  }
}

export default withRouter(History)

PageOne.js

import React, { Fragment, Component } from 'react'

class PageOne extends Component {

   componentDidMount(){
      if(this.props.location.state && this.props.location.state.from != '/pageone')
      this.props.history.push({
         pathname: '/pageone',
         state: { 
             from: this.props.location.pathname
         }
       });
   }

   render() {
      return (
         <Fragment>
            <div className="container-fluid">
               <div className="row d-flex justify-content-center">
                  <h2>Page One</h2>
               </div>
            </div>
         </Fragment>
      )
   }
}

export default PageOne

ps maaf kodenya terlalu besar untuk memposting semuanya di sini


1
Ini harus menjadi jawaban yang diterima pada '19. React Router menyediakan komponen urutan yang lebih tinggi (HOC) yang disebut "withRouter" sehingga Anda dapat membungkus komponen Anda untuk memiliki akses ke props seperti riwayat dan lokasi.

1
ya seperti di withRouter di HOC di bagian Anda yang membungkus komponen, akan memberikan data riwayat dan lokasi. Tidak ada yang menantang terus membaca dan tidak pernah puas.
Anupam Maurya

Bolehkah saya bertanya mengapa Anda meneruskan tanda plus ke gofungsi history.go(+1):? history.go(1)Seharusnya cukup.
gion_13


8

Ini adalah komponen BackButton yang berfungsi (React 0.14):

var React = require('react');
var Router = require('react-router');

var History = Router.History;

var BackButton = React.createClass({
  mixins: [ History ],
  render: function() {
    return (
      <button className="back" onClick={this.history.goBack}>{this.props.children}</button>
    );
  }
});

module.exports = BackButton;

Tentu saja Anda dapat melakukan sesuatu seperti ini jika tidak ada riwayat:

<button className="back" onClick={goBack}>{this.props.children}</button>

function goBack(e) {
  if (/* no history */) {
    e.preventDefault();
  } else {
    this.history.goBack();
  }
}

7

Untuk react-router v2.x ini telah berubah. Inilah yang saya lakukan untuk ES6:

import React from 'react';
import FontAwesome from 'react-fontawesome';
import { Router, RouterContext, Link, browserHistory } from 'react-router';

export default class Header extends React.Component {

  render() {
    return (
      <div id="header">
        <div className="header-left">
          {
            this.props.hasBackButton &&
            <FontAwesome name="angle-left" className="back-button" onClick={this.context.router.goBack} />
          }
        </div>
        <div>{this.props.title}</div>
      </div>
    )
  }
}

Header.contextTypes = {
  router: React.PropTypes.object
};

Header.defaultProps = {
  hasBackButton: true
};

Header.propTypes = {
  title: React.PropTypes.string
};

6

Kembali ke halaman tertentu :

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

  const history = useHistory();
  
  const routeChange = () => {
    let path = '/login';
    history.push(path);
  };

Kembali ke halaman sebelumnya :

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

  const history = useHistory();
  
  const routeChange = () => {
    history.goBack()
  };

2
terima kasih, ini adalah jawaban tahun 2020 yang hebat! Jawaban yang diterima sangat 2015.
beeftosino

5

Di react-router v4.x Anda dapat menggunakan history.goBackyang setara dengan history.go(-1).

App.js

import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";
import Back from "./Back";

const styles = {
  fontFamily: "sans-serif",
  textAlign: "left"
};

const App = () => (
  <div style={styles}>
    <Router>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/contact">Contact</Link></li>
        </ul>

        <hr />

        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />

        <Back />{/* <----- This is component that will render Back button */}
      </div>
    </Router>
  </div>
);

render(<App />, document.getElementById("root"));

Back.js

import React from "react";
import { withRouter } from "react-router-dom";

const Back = ({ history }) => (
  <button onClick={history.goBack}>Back to previous page</button>
);

export default withRouter(Back);

Demo: https://codesandbox.io/s/ywmvp95wpj

Harap diingat bahwa dengan menggunakan historypengguna Anda dapat keluar karena history.goBack()dapat memuat halaman yang telah dikunjungi pengunjung sebelum membuka aplikasi Anda.


Untuk mencegah situasi seperti yang dijelaskan di atas, saya telah membuat perpustakaan sederhana react-router-last-location yang mengawasi lokasi terakhir pengguna Anda.

Penggunaannya sangat mudah. Pertama, Anda perlu menginstal react-router-domdan react-router-last-locationdari npm.

npm install react-router-dom react-router-last-location --save

Kemudian gunakan LastLocationProviderseperti di bawah ini:

App.js

import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { LastLocationProvider } from "react-router-last-location";
//              ↑
//              |
//              |
//
//       Import provider
//
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";
import Back from "./Back";

const styles = {
  fontFamily: "sans-serif",
  textAlign: "left"
};

const App = () => (
  <div style={styles}>
    <h5>Click on About to see your last location</h5>
    <Router>
      <LastLocationProvider>{/* <---- Put provider inside <Router> */}
        <div>
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/about">About</Link></li>
            <li><Link to="/contact">Contact</Link></li>
          </ul>

          <hr />

          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/contact" component={Contact} />

          <Back />
        </div>
      </LastLocationProvider>
    </Router>
  </div>
);

render(<App />, document.getElementById("root"));

Back.js

import React from "react";
import { Link } from "react-router-dom";
import { withLastLocation } from "react-router-last-location";
//              ↑
//              |
//              |
//
//    `withLastLocation` higher order component
//    will pass `lastLocation` to your component               
//
//                   |
//                   |
//                   ↓
const Back = ({ lastLocation }) => (
  lastLocation && <Link to={lastLocation || '/'}>Back to previous page</Link>
);


//          Remember to wrap
//   your component before exporting
//
//                   |
//                   |
//                   ↓
export default withLastLocation(Back);

Demo: https://codesandbox.io/s/727nqm99jj


Bagaimana Anda hanya menarik objek LastLocation ke dalam komponen yang membutuhkannya - yaitu, saya ingin menggunakannya secara terprogram, daripada dalam beberapa keluaran yang ditampilkan seperti contoh Anda: if (lastLocation == 'about')
dmayo

Tidak yakin apakah saya memahami Anda dengan benar, jadi perbaiki jika saya salah. Apakah Anda ingin menggunakan di lastLocationluar React atau mungkin dengan mengatakan I'd like to use it programmatically, apakah Anda hanya ingin dapat mengimpornya import { lastLocation } from '...'?
hinok

5

Yang berhasil bagi saya adalah mengimpor withRouter di bagian atas file saya;

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

Kemudian gunakan untuk membungkus fungsi yang diekspor di bagian bawah file saya;

export default withRouter(WebSitePageTitleComponent)

Yang kemudian memungkinkan saya untuk mengakses properti riwayat Router. Kode sampel lengkap di bawah ini!

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

import PropTypes from 'prop-types'

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

  handleClick() {
    event.preventDefault()
    this.props.history.goBack()
  }

  render() {
    return (
      <div className="page-title">
        <a className="container" href="/location" onClick={this.handleClick}>
          <h1 className="page-header">
            { this.props.title }
          </h1>
        </a>
      </div>
    )
  }
}

const { string, object } = PropTypes

TestComponent.propTypes = {
  title: string.isRequired,
  history: object
}

export default withRouter(TestComponent)

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

this.props.history.goBack();

Saya menggunakan versi ini

"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",

2

Satu-satunya solusi yang berhasil bagi saya adalah yang paling sederhana. Tidak perlu impor tambahan.

<a href="#" onClick={() => this.props.history.goBack()}>Back</a>

Tks, IamMHussain


Sangat bagus. Sederhana dan Rendah Hati
Dinesh Kanivu

1

Panggil komponen berikut seperti ini:

<BackButton history={this.props.history} />

Dan inilah komponennya:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
class BackButton extends Component {
  constructor() {
    super(...arguments)

    this.goBack = this.goBack.bind(this)
  }

  render() {
    return (
      <button
        onClick={this.goBack}>
          Back
      </button>
    )
  }

  goBack() {
    this.props.history.goBack()
  }
}

BackButton.propTypes = {
  history: PropTypes.object,
}

export default BackButton

Saya menggunakan:

"react": "15.6.1"
"react-router": "4.2.0"

1

REDUX

Anda juga dapat menggunakan react-router-reduxyang memiliki goBack()dan push().

Berikut adalah paket sampler untuk itu:

Di titik masuk aplikasi Anda, Anda perlu ConnectedRouter, dan terkadang koneksi rumit untuk dihubungkan adalah historyobjeknya. Middleware Redux mendengarkan perubahan sejarah:

import React from 'react'
import { render } from 'react-dom'
import { ApolloProvider } from 'react-apollo'
import { Provider } from 'react-redux'
import { ConnectedRouter } from 'react-router-redux'
import client from './components/apolloClient'
import store, { history } from './store'
import Routes from './Routes'
import './index.css'

render(
  <ApolloProvider client={client}>
    <Provider store={store}>
      <ConnectedRouter history={history}>
        <Routes />
      </ConnectedRouter>
    </Provider>
  </ApolloProvider>,
  document.getElementById('root'),
)

Saya akan menunjukkan cara untuk menghubungkan history. Perhatikan bagaimana riwayat diimpor ke toko dan juga diekspor sebagai tunggal sehingga bisa digunakan di titik masuk aplikasi:

import { createStore, applyMiddleware, compose } from 'redux'
import { routerMiddleware } from 'react-router-redux'
import thunk from 'redux-thunk'
import createHistory from 'history/createBrowserHistory'
import rootReducer from './reducers'

export const history = createHistory()

const initialState = {}
const enhancers = []
const middleware = [thunk, routerMiddleware(history)]

if (process.env.NODE_ENV === 'development') {
  const { devToolsExtension } = window
  if (typeof devToolsExtension === 'function') {
    enhancers.push(devToolsExtension())
  }
}

const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers)
const store = createStore(rootReducer, initialState, composedEnhancers)

export default store

Blok contoh di atas menunjukkan bagaimana memuat react-router-reduxpembantu middleware yang menyelesaikan proses pengaturan.

Saya pikir bagian selanjutnya ini benar-benar ekstra, tetapi saya akan memasukkannya kalau-kalau seseorang di masa depan menemukan manfaat:

import { combineReducers } from 'redux'
import { routerReducer as routing } from 'react-router-redux'

export default combineReducers({
  routing, form,
})

Saya menggunakan routerReducersepanjang waktu karena memungkinkan saya untuk memaksa memuat ulang Komponen yang biasanya tidak perlu dilakukan shouldComponentUpdate. Contoh yang jelas adalah ketika Anda memiliki Nav Bar yang seharusnya diperbarui ketika pengguna menekan NavLinktombol. Jika Anda menempuh jalan itu, Anda akan belajar bahwa metode koneksi Redux digunakan shouldComponentUpdate. Dengan routerReducer, Anda dapat menggunakan mapStateToPropsuntuk memetakan perubahan perutean ke Nav Bar, dan ini akan memicunya untuk memperbarui ketika objek riwayat berubah.

Seperti ini:

const mapStateToProps = ({ routing }) => ({ routing })

export default connect(mapStateToProps)(Nav)

Maafkan saya saat saya menambahkan beberapa kata kunci tambahan untuk orang-orang: jika komponen Anda tidak diperbarui dengan benar, selidiki shouldComponentUpdatedengan menghapus fungsi hubungkan dan lihat apakah itu memperbaiki masalah. Jika demikian, tarik routerReducerdan komponen akan diperbarui dengan benar saat URL berubah.

Sebagai penutup, setelah melakukan semua itu, Anda dapat menelepon goBack()atau push()kapan pun Anda mau!

Coba sekarang di beberapa komponen acak:

  1. Impor masuk connect()
  2. Anda bahkan tidak membutuhkan mapStateToPropsataumapDispatchToProps
  3. Impor goBack dan tekan dari react-router-redux
  4. Panggilan this.props.dispatch(goBack())
  5. Panggilan this.props.dispatch(push('/sandwich'))
  6. Rasakan emosi positif

Jika Anda membutuhkan lebih banyak pengambilan sampel, lihat: https://www.npmjs.com/package/react-router-redux


1

Cukup gunakan seperti ini

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

1

Bereaksi Router v6

useNavigate Hook adalah cara yang disarankan untuk kembali sekarang:

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

function App() {
  const navigate = useNavigate();

  return (
    <>
      <button onClick={() => navigate(-1)}>go back</button>
      <button onClick={() => navigate(1)}>go forward</button>
    </>
  );
}

Contoh Codesandbox

Mundur / maju beberapa entri tumpukan riwayat:
<button onClick={() => navigate(-2)}>go two back</button>
<button onClick={() => navigate(2)}>go two forward</button>
Pergi ke rute tertentu:
navigate("users") // go to users route, like history.push
navigate("users", { replace: true }) // go to users route, like history.replace
navigate("users", { state }) // go to users route, pass some state in

useNavigate menggantikan useHistory untuk mendukung mode React Suspense / Concurrent mendatang dengan lebih baik.


Saya mencoba mencoba ini tetapi saya mendapat kesalahan:Attempted import error: 'useNavigate' is not exported from 'react-router-dom'.
Geek

1
@Tangkap bagus. Dengan v6.0.0-beta.0, devs telah membuat historypaket menjadi dependensi peer. Lihatlah Codesandbox yang diperbarui, yang berfungsi kembali sekarang.
ford04

0

Potongan kode ini akan melakukan trik untuk Anda.

this.context.router.history.goBack()

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.