react-router bir sayfaya geri dön geçmişi nasıl yapılandırırsınız?


123

Biri bana belirli bir rotadan önceki sayfaya nasıl geri dönebileceğimi söyleyebilir mi?

Bu kodu kullanırken:

var BackButton = React.createClass({

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

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

Bu hatayı alın, yönlendirici geçmişi olmadığı için goBack () yok sayıldı

İşte rotalarım:

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

Bir çözüm bulduysanız, lütfen burada paylaşın. Teşekkürler.
user261002

Yanıtlar:


44

Ben sadece bunu böyle intializing tarafından Yönlendiricinizde BrowserHistory etkinleştirmeniz gerekir düşünüyorum: <Router history={new BrowserHistory}>.

Bundan önce BrowserHistory,'react-router/lib/BrowserHistory'

Umarım bu yardımcı olur !

GÜNCELLEME: ES6'da örnek

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

merhaba, aynı sorunla karşı karşıyayız. lütfen daha ayrıntılı olarak açıklar mısınız? TEŞEKKÜRLER
user261002

23
Bu nasıl doğru cevap? Bu soruya cevap bile vermiyor. @ bomber
GN.

15
Bunu okuyan herkes için. Bunu bir alt bileşenden yapmak istiyorsanız. Geçmiş nesnesini adresinde bulabilirsiniz this.props.history. Böylece kod şu hale gelirthis.props.history.goBack
Sisir

3
React-router 4'e ne dersiniz? BrowserHistory'yi artık desteklediğini sanmıyorum.
Akshay Lokur

1
React-router-dom sürüm 5'ten itibaren, geçmiş BrowserRouter tarafından örtük olarak oluşturulur ve props aracılığıyla kullanılabilir, buna props.history aracılığıyla erişebilirsiniz.
Srikanth Kyatham

98

React v16 ve ReactRouter v4.2.0 ile güncelleme (Ekim 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>
    )
  }
}

React v15 ve ReactRouter v3.0.0 ile güncelleme (Ağustos 2016):

var browserHistory = ReactRouter.browserHistory;

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

Gömülü bir iframe ile biraz daha karmaşık bir örnekle bir keman oluşturdu: https://jsfiddle.net/kwg1da3a/

React v14 ve ReacRouter v1.0.0 (10 Eyl 2015)

Bunu yapabilirsiniz:

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

Geri dönmek için gerekli geçmişe sahip olduğunuza dikkat etmelisiniz. Doğrudan sayfaya tıklar ve ardından geri tıklarsanız, sizi uygulamanızdan önceki tarayıcı geçmişine geri götürür.

Bu çözüm, her iki senaryoyu da halledecektir. Bununla birlikte, geri düğmesiyle sayfa içinde dolaşabilen (ve tarayıcı geçmişine eklenebilen) bir iframe'i işlemeyecektir. Açıkçası, bunun tepki yönlendiricide bir hata olduğunu düşünüyorum. Burada oluşturulan sorun: https://github.com/rackt/react-router/issues/1874


Bunu bağlam kullanmadan yapmanın bir yolu olsaydı iyi olurdu?
Adam D

1
Ayrıca, kuruluma bağlı olarak this.context.router.history.goBack yerine this.props.history.goBack kullanıyor olabilir
PhoenixB

54
  1. ithalat withRouter

    import { withRouter } from 'react-router-dom';
  2. Bileşeninizi şu şekilde dışa aktarın:

    export withRouter(nameofcomponent) 
  3. Örnek, düğme tıklandığında, ara goBack:

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

react-router-domV4.3'te test edildi


2
BTW, içe aktarmadan veya kullanmadan bile benim için çalışıyor withRouter. Belki sadece tarayıcı geçmişi yerel API'sini kullanıyoruz. Ama sorun olur mu?
Gianfranco P.

1
Bu güzel çözüm. Kullanıcı doğrudan URL'yi kullanarak sayfaya geldiğinde tek sorun -> geçmişe sahip olmadığı için uygulamayı bozacaktır.
skryvets

2
En iyi açıklama burada
Z_z_Z

@MichaelFreidgeim, kod pasajınızı yükler misiniz, böylece kontrol edeceğim ve doğrulanacağım
gaurav makwana


32

React-router, durumsuz işlev kullanan mixins içermeyen ES6 yöntemi.

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

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

3
Çözümünüzü denerken bir tarayıcı uyarısı alıyorum:export 'browserHistory' was not found in 'react-router'
Ralph David Abernathy

2
browserHistory yalnızca v2 ve v3'te mevcuttur. V4 kullanıyorsanız, geçiş kılavuzunu okumalısınız: github.com/ReactTraining/react-router/blob/…
ptorsson

@Ralp, bu hata mesajını alırsanız, şuna bakın: stackoverflow.com/questions/49787659/…
Miles M.

13

React Hook'larını Kullanma

İthalat:

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

Durum bilgisi olmayan bileşende:

  let history = useHistory();

Etkinlikte

history.goBack()

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

Kancaları sevdiğim için bundan bahsettiğin için teşekkürler. Şimdiye kadar Router ile kullanıyorum.
newman

10

React-router v4 Live Example ile React 16.0'ı kullanarak çalışma örneğime göz atın . Github kodunu kontrol edin

Kullanım withRoutervehistory.goBack()

Uyguladığım fikir bu ...

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 üzgünüm kod hepsini buraya göndermek için büyük


1
19'dan beri kabul edilen cevap bu olmalı. React Router, "withRouter" adı verilen daha yüksek bir bileşen (HOC) sağlar, böylece bileşeninizi geçmiş ve konum gibi araçlara erişim sağlamak için sarabilirsiniz.

1
Evet, HOC'daki Router ile olduğu gibi, bileşen parçanızı sararken, geçmiş ve konum verilerini sağlayacaktır. Zorlayıcı hiçbir şey okumayı sürdürmez ve asla yetinmez.
Anupam Maurya

Eğer artı işaretini geçmesi sorabilir miyim gofonksiyonu: history.go(+1)? history.go(1)yeterli olmalı.
gion_13

10

Bu, Tarayıcı ve Karma geçmişi ile çalışır.

this.props.history.goBack();

8

Bu çalışan bir BackButton bileşenidir (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;

Geçmiş yoksa tabii ki böyle bir şey yapabilirsiniz:

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

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

7

React-router v2.x için bu değişti. İşte ES6 için yaptığım şey:

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

Belirli bir sayfaya geri dönün :

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

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

Önceki sayfaya geri dönün :

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

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

2
teşekkürler, bu harika bir 2020 cevabı! Kabul edilen cevap
2015'ti

5

React-router v4.x'te history.goBack, eşdeğerini kullanabilirsiniz 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

Lütfen historykullanıcılarınızı kullanarak ayrılabileceğinizi unutmayın, çünkü history.goBack()uygulamanızı açmadan önce ziyaretçinin ziyaret ettiği bir sayfayı yükleyebilir.


Yukarıda açıklandığı gibi böyle bir durumu önlemek için, kullanıcılarınızın son konumunu izleyen basit bir react-router-last-location kitaplığı oluşturdum .

Kullanım çok basittir. Öncelikle yüklemeniz gerekir react-router-domve react-router-last-locationgelen npm.

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

Ardından LastLocationProvideraşağıdaki gibi kullanın :

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


LastLocation nesnesini ihtiyacı olan bileşene nasıl çekersiniz
yani

Sizi doğru anladığımdan emin değilim, bu yüzden lütfen yanılıyorsam beni düzeltin. lastLocationReact'in dışında kullanmak ister misiniz I'd like to use it programmatically, yoksa şöyle diyerek , sadece onu içe aktarma yeteneğine sahip olmak ister misiniz import { lastLocation } from '...'?
hinok

5

Benim için işe yarayan şey, dosyamın üst kısmındaki Router ile içe aktarmaktı;

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

Ardından, dışa aktarılan işlevi dosyamın altına sarmak için kullanın;

export default withRouter(WebSitePageTitleComponent)

Bu da daha sonra Yönlendiricinin geçmiş nesnesine erişmeme izin verdi. Tam örnek kod aşağıdadır!

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

Bu sürümleri kullanıyorum

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

2

Benim için işe yarayan tek çözüm en basit olanıydı. Ek ithalat gerekmez.

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

Tks, IamMHussain


Çok hoş. Simple and Humble
Dinesh Kanivu

1

Aşağıdaki bileşeni şu şekilde arayın:

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

Ve işte bileşen:

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

Kullanıyorum:

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

1

REDUX

Ayrıca react-router-reduxhangisinin sahip olduğunu goBack()ve push().

İşte bunun için bir örnekleyici paketi:

Uygulamanızın giriş noktasında, ihtiyaç duyarsınız ConnectedRouterve bazen bağlantı kurmak için zor bir bağlantı amaçtır history. Redux ara yazılım, geçmiş değişikliklerini dinler:

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'),
)

Sana bağlanmanın bir yolunu göstereceğim history. Geçmişin mağazaya nasıl aktarıldığına ve ayrıca uygulamanın giriş noktasında kullanılabilmesi için tekli olarak nasıl dışa aktarıldığına dikkat edin:

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

Yukarıdaki örnek blok react-router-redux, kurulum sürecini tamamlayan ara yazılım yardımcılarının nasıl yükleneceğini gösterir .

Bir sonraki bölümün tamamen ekstra olduğunu düşünüyorum, ancak gelecekte birisinin fayda görmesi durumunda onu ekleyeceğim:

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

export default combineReducers({
  routing, form,
})

Her routerReducerzaman kullanıyorum çünkü normalde neden olmayan Bileşenleri yeniden yüklemeye zorlamama izin veriyor shouldComponentUpdate. Bunun en bariz örneği, bir kullanıcı bir NavLinkdüğmeye bastığında güncellenmesi beklenen bir Gezinme Çubuğuna sahip olduğunuz zamandır . Bu yoldan giderseniz, Redux'un bağlantı yönteminin kullandığını öğreneceksiniz shouldComponentUpdate. İle routerReducer, mapStateToPropsyönlendirme değişikliklerini Gezinme Çubuğu'na eşlemek için kullanabilirsiniz ve bu, geçmiş nesnesi değiştiğinde güncellenmesini tetikler.

Bunun gibi:

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

export default connect(mapStateToProps)(Nav)

İnsanlar için fazladan anahtar sözcükler eklerken beni affedin: Bileşeniniz düzgün bir şekilde güncellenmiyorsa shouldComponentUpdate, bağlantı işlevini kaldırarak araştırın ve sorunu çözüp çözmediğine bakın. Öyleyse, çekin routerReducerve bileşen, URL değiştiğinde düzgün bir şekilde güncellenecektir.

Kapanışta, tüm bunları yaptıktan sonra, istediğiniz zaman goBack()veya push()istediğiniz zaman arayabilirsiniz !

Şimdi rastgele bir bileşende deneyin:

  1. İçeri aktar connect()
  2. Hatta gerek yok mapStateToPropsyamapDispatchToProps
  3. GoBack'te içe aktarın ve şuradan aktarın react-router-redux
  4. Aramak this.props.dispatch(goBack())
  5. Aramak this.props.dispatch(push('/sandwich'))
  6. Olumlu duygu yaşayın

Daha fazla örneklemeye ihtiyacınız varsa şu adrese göz atın: https://www.npmjs.com/package/react-router-redux


1

Bunun gibi kullan

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

1

React Router v6

useNavigate Kanca şimdi geri dönmenin önerilen yoludur:

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

Codesandbox örneği

Birden çok geçmiş yığını girişini geri / ileri sarın:
<button onClick={() => navigate(-2)}>go two back</button>
<button onClick={() => navigate(2)}>go two forward</button>
Belirli rotaya gidin:
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 gelecek React Suspense / Concurrent modunu daha iyi desteklemekuseHistory için yerini alır .


Bunu denemeyi denedim ama hatayı aldım:Attempted import error: 'useNavigate' is not exported from 'react-router-dom'.
Geek

1
@Geek iyi yakala. İle v6.0.0-beta.0geliştiriciler, historypaketi bir eş bağımlılığı haline getirdi . Şimdi tekrar çalışan güncellenmiş Codesandbox'a bir göz atın.
ford04

0

Bu kod parçası sizin için hile yapacak.

this.context.router.history.goBack()

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.