react-router (v4) как вернуться?

91

Пытаюсь понять, как мне вернуться на предыдущую страницу. Я использую[react-router-v4][1]

Это код, который я настроил на своей первой целевой странице:

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

Чтобы перейти на следующие страницы, я просто делаю:

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

Однако как я могу вернуться на предыдущую страницу? Пробовал несколько вещей, перечисленных ниже, но безуспешно: 1.this.props.history.goBack();

Выдает ошибку:

TypeError: null не является объектом (оценка this.props)

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

Выдает ошибку:

TypeError: null не является объектом (оценка this.context)

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

Выдает ошибку:

TypeError: null не является объектом (оценка this.props)

Размещение Page1кода здесь ниже:

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;
Акшай Локур
источник
Какие несколько вещей вы пробовали?
Вивек Доши
3
попробуйте this.props.history.goBack(); github.com/ReactTraining/react-router/blob/…
Bascax
@VivekDoshi: Добавил то, что я пробовал, вместе с ошибками, с которыми я столкнулся
Акшай
@AkshayLokur, не могли бы вы опубликовать полный код, откуда вы пытаетесь выполнить this.props.history.goBack () ;?
Вивек Доши
@VivekDoshi: Готово, пожалуйста, посмотрите, спасибо
Акшай

Ответы:

126

Думаю, проблема в привязке:

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>

Как я предполагал до того, как вы разместили код:

constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
    this.handleBack = this.handleBack.bind(this); // you are missing this line
}
Вивек Доши
источник
не работает, когда в браузере нажата кнопка «Назад», componentDidUpdateа window.onpopstate?
jmunsch 02
27
this.props.history.goBack();

Это правильное решение для реактивного маршрутизатора v4

Но вы должны помнить, что вам нужно убедиться, что this.props.history существует.

Это означает, что вам нужно вызвать эту функцию this.props.history.goBack();внутри компонента, заключенного в <Route />

Если вы вызовете эту функцию в компоненте, находящемся глубже в дереве компонентов, она не будет работать.

РЕДАКТИРОВАТЬ:

Если вы хотите иметь объект истории в компоненте, который находится глубже в дереве компонентов (который не заключен в оболочку <Route>), вы можете сделать что-то вроде этого:

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

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

export default withRouter(Demo);
Хоанг Тринь
источник
Итак, как это может работать? Как можно вернуться в историю откуда угодно?
Felipe
@Felipe Ты можешь вернуться откуда угодно. Я просто имею в виду, что вам нужно добавить эту строку кода в компоненты контейнера, чтобы получить объект «история», не используйте эту строку кода из компонентов Presentation, которые не упакованы Route ( medium.com/@dan_abramov / smart-and-dumb-components-7ca2f9a7c7d0 )
Hoang Trinh
@ Фелипе: Привет, пожалуйста, проверьте мой отредактированный ответ. Думаю, это ответ на ваш вопрос.
Hoang Trinh
Спасибо за правку withRouter, которая исправила это для меня.
Matthew Rideout
17

Для использования с React Router v4 и функциональным компонентом в любом месте dom-дерева.

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);
фриппера
источник
Это хорошее решение, поскольку в нем не используется метод жизненного цикла. Мне он также понятнее, потому что он обозначает то, что проходит, в данном случае объект истории.
AC Patrice
Версия с толстой стрелкой всегда выглядит намного чище, спасибо за это.
egdavid
9

У каждого ответа здесь есть части общего решения. Вот полное решение, которое я использовал, чтобы заставить его работать внутри компонентов глубже, чем использовался Route:

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

^ Эта вторая строка нужна вам для импорта функции и для экспорта компонента внизу страницы.

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

^ Требуется стрелочная функция, а не просто onClick = {this.props.history.goBack ()}

export default withRouter(MyPage)

^ оберните имя вашего компонента с помощью 'withRouter ()'

foureyedraven
источник
5

Можете ли вы предоставить код, в котором вы используете this.props.history.push('/Page2'); ?

Вы пробовали метод goBack ()?

this.props.history.goBack();

Он указан здесь https://reacttraining.com/react-router/web/api/history

С живым примером здесь https://reacttraining.com/react-router/web/example/modal-gallery

Альфредо Ре
источник
Это вызывает у меня ошибку, см. Обновленный вопрос выше
Акшай
Можете ли вы также добавить код this.props.history.push('/Page2');? Если там this.propsне null, он должен работать.
Alfredo Re
Ничего особенного, я просто вызываю это нажатием кнопки «Назад» в моем компоненте
Акшай
5

Вот самый чистый и простой способ решения этой проблемы, который также сводит на нет возможные подводные камни this keyword. Используйте функциональные компоненты:

import { withRouter } from "react-router-dom"; обернуть componentили лучше App.jsс withRouter() HOCэтим маркам historyбыть доступны «приложение-широким». упаковка вашего компонента делает его только history available for that specific компонентом по вашему выбору.

Так что у тебя есть:

  1. export default withRouter(App);

  2. В среде Redux таким образом export default withRouter( connect(mapStateToProps, { <!-- your action creators -->})(App), );вы даже должны иметь возможность пользователя historyиз создателей ваших действий.

в вашем componentсделать следующее:

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 useHistoryэкспортируется только из последней версии 5.1, react-router-domпоэтому обязательно обновите пакет. Однако волноваться не о чем. о многих загвоздках this keyword.

Вы также можете сделать это повторно используемым компонентом для использования в вашем приложении.


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

Лоуренс Иглз
источник
2
Благодарю. Но почему мой компонент не перерисовывается, когда я возвращаюсь в браузер?
Стефан
0

Пытаться:

this.props.router.goBack()
Родий
источник
Это вызывает у меня ошибку, см. Обновленный вопрос выше
Акшай
откуда вы берете свой роутер или историческую опору? Убедитесь, что вы получаете его из родительского компонента или страницы (например, console.log (this.props) в функции рендеринга, и убедитесь, что вы печатаете опору маршрутизатора, чтобы иметь возможность ее использовать. Мне кажется, вы в вашем компоненте нет маршрутизатора.
Rodius
0

Просто используйте

<span onClick={() => this.props.history.goBack()}>Back</span>
IamMHussain
источник
0

Надеюсь, это кому-то поможет:

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

...
Ник Бристоль
источник
0

Может это кому поможет.

Я использовал history.replace()для перенаправления, поэтому, когда я пытался использовать history.goBack(), меня отправляли на предыдущую страницу до страницы, с которой я работал. Поэтому я изменил метод history.replace()на, history.push()чтобы можно было сохранить историю, и я мог вернуться.

Юлия Рамос
источник
0

Я не уверен, сталкивался ли кто-нибудь еще с этой проблемой или, возможно, нужно это увидеть. Но я потратил около 3 часов, пытаясь решить эту проблему:

Я хотел реализовать простой goBack () одним нажатием кнопки. Я думал, что у меня хорошее начало, потому что мой App.js уже был обернут в маршрутизаторе, и я импортировал {BrowserRouter as Router} из 'response-router-dom'; ... Поскольку элемент Router позволяет мне оценивать объект истории.

пример:

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;

НО проблема была в моем модуле Nav (дочерний компонент), мне пришлось «импортировать {withRouter} из« response-router-dom »; а затем принудительно выполнить экспорт с помощью:

export default withRouter(Nav);

пример:

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

Таким образом, withRouter был создан из-за известной проблемы в React, когда в определенных сценариях, когда наследование от маршрутизатора отклоняется, необходим принудительный экспорт.

user14199788
источник
0

Можно использовать history.goBack()в функциональном компоненте. Именно так.

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

  return (
   <button onClick={() => history.goBack()}>Previous</button>
  )
}
Зишан Сафдар
источник