react-router (v4) jak wrócić?

91

Próbuję wymyślić, jak mogę wrócić do poprzedniej strony. ja używam[react-router-v4][1]

Oto kod, który skonfigurowałem na mojej pierwszej stronie docelowej:

<Router>
  <div>
    <Link to="/"><div className="routerStyle"><Glyphicon glyph="home" /></div></Link>
    <Route exact path="/" component={Page1}/>
    <Route path="/Page2" component={Page2}/>
    <Route path="/Page3" component={Page3}/>
  </div>
</Router>

Aby przejść na kolejne strony, po prostu robię:

this.props.history.push('/Page2');

Jak jednak mogę wrócić do poprzedniej strony? Próbowałem kilku rzeczy, takich jak wymienione poniżej, ale bez powodzenia: 1.this.props.history.goBack();

Daje błąd:

TypeError: null nie jest obiektem (ocena „this.props”)

  1. this.context.router.goBack();

Daje błąd:

TypeError: null nie jest obiektem (ocena „this.context”)

  1. this.props.history.push('/');

Daje błąd:

TypeError: null nie jest obiektem (ocena „this.props”)

Umieszczając Page1kod tutaj poniżej:

import React, {Component} from 'react';
import {Button} from 'react-bootstrap';

class Page1 extends Component {
  constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
  }


  handleNext() {
    this.props.history.push('/page2');
  }

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


  /*
   * Main render method of this class
   */
  render() {
    return (
      <div>
        {/* some component code */}


        <div className="navigationButtonsLeft">
          <Button onClick={this.handleBack} bsStyle="success">&lt; Back</Button>
        </div>
        <div className="navigationButtonsRight">
          <Button onClick={this.handleNext} bsStyle="success">Next &gt;</Button>
        </div>

      </div>
    );
  }


export default Page1;
Akshay Lokur
źródło
Jakich kilku rzeczy próbowałeś?
Vivek Doshi,
3
spróbuj this.props.history.goBack(); github.com/ReactTraining/react-router/blob/ ...
baskax
@VivekDoshi: Dodano to, co wypróbowałem, wraz z napotkanymi błędami
Akshay Lokur
@AkshayLokur, czy możesz przesłać pełny kod, z którego próbujesz wykonać this.props.history.goBack () ;?
Vivek Doshi,
@VivekDoshi: Gotowe, proszę spojrzeć, dzięki
Akshay Lokur

Odpowiedzi:

127

Myślę, że problem dotyczy oprawy:

constructor(props){
   super(props);
   this.goBack = this.goBack.bind(this); // i think you are missing this
}

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

.....

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

Jak założyłem przed wysłaniem kodu:

constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
    this.handleBack = this.handleBack.bind(this); // you are missing this line
}
Vivek Doshi
źródło
nie działa, gdy przycisk Wstecz przeglądarki jest wciśnięty i włączony componentDidUpdatei window.onpopstate?
jmunsch
27
this.props.history.goBack();

To jest poprawne rozwiązanie dla React-router v4

Ale jedną rzeczą, o której powinieneś pamiętać, jest to, że musisz się upewnić, że this.props.history istnieje.

Oznacza to, że musisz wywołać tę funkcję this.props.history.goBack();wewnątrz komponentu, który jest opakowany przez <Route />

Jeśli wywołasz tę funkcję w komponencie znajdującym się głębiej w drzewie komponentów, nie zadziała.

EDYTOWAĆ:

Jeśli chcesz mieć obiekt historii w komponencie, który jest głębiej w drzewie komponentów (który nie jest zawijany przez <Route>), możesz zrobić coś takiego:

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

class Demo extends Component {
    ...
    // Inside this you can use this.props.history.goBack();
}

export default withRouter(Demo);
Hoang Trinh
źródło
Więc jak to działa? Jak możesz cofnąć się do historii z dowolnego miejsca?
Felipe
@Felipe Możesz wrócić z dowolnego miejsca. Chodzi mi tylko o to, że musisz dodać ten wiersz kodu w komponentach kontenera, aby uzyskać obiekt "historii", nie używaj tego wiersza kodu z komponentów prezentacyjnych, które nie są opakowane przez Route ( medium.com/@dan_abramov / smart-and-dumb-components-7ca2f9a7c7d0 )
Hoang Trinh
@Felipe: Cześć, sprawdź moją zredagowaną odpowiedź. Myślę, że to odpowiada na twoje pytanie.
Hoang Trinh
Dziękuję za edycję withRouter, która rozwiązała problem.
Matthew Rideout
17

Do użytku z React Router v4 i komponentem funkcjonalnym w dowolnym miejscu w drzewie domeny.

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

const GoBack = ({ history }) => <img src="./images/back.png" onClick={() => history.goBack()} alt="Go back" />;

export default withRouter(GoBack);
frippera
źródło
To dobre rozwiązanie, ponieważ nie wykorzystuje metody cyklu życia. Jest to dla mnie również jaśniejsze, ponieważ oznacza to, przez co przechodzi, w tym przypadku obiekt historii.
AC Patrice
Wersja z grubą strzałą zawsze wygląda dla mnie o wiele czyściej, dzięki za to.
egdavid
9

Każda odpowiedź zawiera części całkowitego rozwiązania. Oto kompletne rozwiązanie, którego użyłem, aby działało wewnątrz komponentów głębiej niż tam, gdzie był używany Route:

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

^ Drugi wiersz jest potrzebny do importowania funkcji i eksportowania komponentu na dole strony.

render() {
  return (
  ...
    <div onClick={() => this.props.history.goBack()}>GO BACK</div>
  )
}

^ Wymagana funkcja strzałki, a po prostu onClick = {this.props.history.goBack ()}

export default withRouter(MyPage)

^ zawiń nazwę komponentu słowem „withRouter ()”

foureyedraven
źródło
5

Czy możesz podać kod, którego używasz this.props.history.push('/Page2');?

Czy wypróbowałeś metodę goBack ()?

this.props.history.goBack();

Jest wymieniony tutaj https://reacttraining.com/react-router/web/api/history

Z przykładem na żywo tutaj https://reacttraining.com/react-router/web/example/modal-gallery

Alfredo Re
źródło
To daje mi błąd, zobacz zaktualizowane pytanie powyżej
Akshay Lokur
Czy możesz również dodać kod this.props.history.push('/Page2');? Jeśli this.propstam nie jest zerowe, powinno działać.
Alfredo Re
Nic, po prostu dzwonię po kliknięciu przycisku Wstecz w moim komponencie
Akshay Lokur,
5

Oto najczystszy i najprostszy sposób rozwiązania tego problemu, który również unieważnia prawdopodobne pułapki związane z this keyword. Użyj funkcjonalnych komponentów:

import { withRouter } from "react-router-dom"; owinąć componentlub lepszy App.jsz withRouter() HOCtych marek historybędzie dostępny „app-wide”. opakowanie twojego komponentu sprawia, że history available for that specific komponent jest tylko twoim wyborem.

Więc masz:

  1. export default withRouter(App);

  2. W środowisku Redux export default withRouter( connect(mapStateToProps, { <!-- your action creators -->})(App), );powinieneś w ten sposób nawet być w stanie korzystać historyz twórców akcji.

w swoim componentwykonaj następujące czynności:

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

const history = useHistory(); // do this inside the component

goBack = () => history.goBack();

<btn btn-sm btn-primary onclick={goBack}>Go Back</btn>

export default DemoComponent;

Gottcha useHistoryjest eksportowana tylko z najnowszej wersji 5.1, react-router-domwięc pamiętaj, aby zaktualizować pakiet. Jednak nie powinieneś się martwić. o wielu problemach z this keyword.

Możesz również uczynić ten komponent wielokrotnego użytku do użycia w całej aplikacji.


function BackButton({ children }) {
  let history = useHistory()
  return (
    <button type="button" onClick={() => history.goBack()}>
      {children}
    </button>
  )
}```
Cheers.

Lawrence Eagles
źródło
2
Dzięki. Ale dlaczego mój komponent nie jest ponownie renderowany po przywróceniu przeglądarki?
Stephane
0

Próbować:

this.props.router.goBack()
Rodius
źródło
To daje mi błąd, zobacz zaktualizowane pytanie powyżej
Akshay Lokur
skąd bierzesz router lub rekwizyt historii? Upewnij się, że pobierasz go ze swojego nadrzędnego komponentu lub strony (np. Console.log (this.props) w funkcji renderowania i sprawdź, czy drukujesz właściwość routera, aby móc go użyć. Wydaje mi się, że ty nie masz routera w swoim komponencie
Rodius,
0

Po prostu użyj

<span onClick={() => this.props.history.goBack()}>Back</span>
IamMHussain
źródło
0

Mam nadzieję, że to komuś pomoże:

import React from 'react';
import * as History from 'history';
import { withRouter } from 'react-router-dom';

interface Props {
  history: History;
}

@withRouter
export default class YourComponent extends React.PureComponent<Props> {

  private onBackClick = (event: React.MouseEvent): void => {
    const { history } = this.props;
    history.goBack();
  };

...
Nick Bristol
źródło
0

Może to komuś pomoże.

history.replace()Używałem do przekierowania, więc kiedy próbowałem użyć history.goBack(), zostałem wysłany na poprzednią stronę przed stroną, z którą pracowałem. Więc zmieniłem metodę history.replace()na, history.push()aby historia mogła zostać zapisana i mógłbym wrócić.

Julia Ramos
źródło
0

Nie jestem pewien, czy ktoś napotkał ten problem lub może potrzebować tego zobaczyć. Ale spędziłem około 3 godzin próbując rozwiązać ten problem:

Chciałem zaimplementować proste goBack () jednym kliknięciem przycisku. Pomyślałem, że to dobry początek, ponieważ mój App.js był już zapakowany w routerze i importowałem {BrowserRouter jako Router} z'reak-router-dom '; ... Ponieważ element Router pozwala mi ocenić obiekt historii.

dawny:

import React from 'react';
import './App.css';
import Splash from './components/Splash';
import Header from './components/Header.js';
import Footer from './components/Footer';
import Info from './components/Info';
import Timer from './components/Timer';
import Options from './components/Options';
import { BrowserRouter as Router, Route } from 'react-router-dom';
function App() {
  return (
    <Router>
      <Header />
      <Route path='/' component={Splash} exact />
      <Route path='/home' component={Info} exact />
      <Route path='/timer' component={Timer} exact />
      <Route path='/options' component={Options} exact />
      <Footer />
    </Router>
  );
}
export default App;

ALE problem był z moim modułem Nav (komponent potomny), musiałem 'zaimportować {withRouter} z'reak-router-dom'; ' a następnie wymuś eksport za pomocą:

export default withRouter(Nav);

dawny:

import React from 'react';
import { withRouter } from 'react-router-dom';
class Nav extends React.Component {
    render() {
        return (
            <div>
                <label htmlFor='back'></label>
                <button id='back' onClick={ () => this.props.history.goBack() }>Back</button>
                <label htmlFor='logOut'></label>
                <button id='logOut' ><a href='./'>Log-Out</a>            
</button>
            </div>
        );
    }
}
export default withRouter(Nav);

Podsumowując, withRouter powstał z powodu znanego problemu w React, gdzie w pewnych sytuacjach, gdy odmawia się dziedziczenia z routera, konieczny jest wymuszony eksport.

user14199788
źródło
0

Możesz użyć history.goBack()w komponencie funkcjonalnym. Takie jak to.

import { useHistory } from 'react-router';
const component = () => { 
  const history = useHistory();

  return (
   <button onClick={() => history.goBack()}>Previous</button>
  )
}
Zeeshan Safdar
źródło