С react-router я могу использовать элемент Link для создания ссылок, которые изначально обрабатываются реагирующим маршрутизатором.

Я вижу, что внутри он вызывает this.context.transitionTo(...).

Я хочу заняться навигацией. Не по ссылке, а из раскрывающегося списка (например). Как я могу сделать это в коде? Что такое this.context?

Я видел миксин Navigation, но могу ли я сделать это без mixins?

1677
George Mauer 26 Июн 2015 в 20:38

29 ответов

Лучший ответ

React Router v5.1.0 с хуками

В React Router> 5.1.0 есть новый хук useHistory, если вы используете React> 16.8.0 и функциональные компоненты.

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

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

React Router v4

В версии 4 React Router есть три подхода к программной маршрутизации внутри компонентов.

  1. Используйте компонент высшего порядка withRouter.
  2. Используйте композицию и визуализируйте <Route>
  3. Используйте context.

React Router - это в основном оболочка библиотеки history. history обрабатывает взаимодействие с window.history браузера для вас с его браузером и хеш-историями. Он также предоставляет историю памяти, которая полезна для сред, у которых нет глобальной истории. Это особенно полезно при разработке мобильных приложений (react-native) и модульном тестировании с помощью Node.

Экземпляр history имеет два метода навигации: push и replace. Если вы думаете о history как о массиве посещенных местоположений, push добавит новое местоположение в массив, а replace заменит текущее местоположение в массиве новым. Обычно при навигации вам нужно использовать метод push.

В более ранних версиях React Router вам нужно было создать свой собственный экземпляр history, но в v4 компоненты <BrowserRouter>, <HashRouter> и <MemoryRouter> будут создавать браузер, хэш, и экземпляры памяти для вас. React Router делает свойства и методы экземпляра history, связанного с вашим маршрутизатором, доступными через контекст под объектом router.

1. Используйте компонент высшего порядка withRouter

Компонент более высокого порядка withRouter внедрит объект history в качестве опоры компонента. Это позволяет вам получить доступ к методам push и replace без необходимости иметь дело с context.

import { withRouter } from 'react-router-dom'
// this also works with react-router-native

const Button = withRouter(({ history }) => (
  <button
    type='button'
    onClick={() => { history.push('/new-location') }}
  >
    Click Me!
  </button>
))

2. Используйте композицию и визуализируйте <Route>

Компонент <Route> предназначен не только для сопоставления местоположений. Вы можете отобразить маршрут без пути, и он всегда будет соответствовать текущему местоположению . Компонент <Route> передает те же реквизиты, что и withRouter, поэтому вы сможете получить доступ к методам history через свойство history.

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

const Button = () => (
  <Route render={({ history}) => (
    <button
      type='button'
      onClick={() => { history.push('/new-location') }}
    >
      Click Me!
    </button>
  )} />
)

3. Используйте контекст *

Но, вероятно, не стоит

Последний вариант следует использовать, только если вы чувствуете себя комфортно при работе с контекстом React модель (Контекстный API React стабилен с v16).

const Button = (props, context) => (
  <button
    type='button'
    onClick={() => {
      // context.history.push === history.push
      context.history.push('/new-location')
    }}
  >
    Click Me!
  </button>
)

// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  })
}

1 и 2 - самые простые варианты для реализации, поэтому для большинства случаев использования они лучше всего подходят.

1776
TankorSmash 26 Апр 2020 в 21:27

React-Router V4

Если вы используете версию 4, вы можете использовать мою библиотеку (плагин Shameless), где вы просто отправляете действие, и все просто работает!

dispatch(navigateTo("/aboutUs"));

трипплер

7
Rich Warrior 8 Авг 2019 в 15:54

В текущей версии React (15.3) this.props.history.push('/location'); работал у меня, но выводил следующее предупреждение:

browser.js: 49 Предупреждение: [response-router] props.history и context.history устарели. Пожалуйста, используйте context.router.

И я решил это с помощью context.router вот так:

import React from 'react';

class MyComponent extends React.Component {

    constructor(props) {
        super(props);
        this.backPressed = this.backPressed.bind(this);
    }

    backPressed() {
        this.context.router.push('/back-location');
    }

    ...
}

MyComponent.contextTypes = {
    router: React.PropTypes.object.isRequired
};

export default MyComponent;
8
David Schumann 26 Мар 2018 в 19:33

Если вы используете хэш или историю браузера, вы можете сделать

hashHistory.push('/login');
browserHistory.push('/login');
10
Zaman Afzal 27 Мар 2018 в 12:46

В реактивном маршрутизаторе v4. Я использую два способа программной маршрутизации.

1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")

Номер два

Заменяет текущую запись в стеке истории

Чтобы получить историю в props, вам, возможно, придется обернуть свой компонент

withRouter

12
Rich Warrior 8 Авг 2019 в 13:41

На основе предыдущего ответа
от Хосе Антонио Постиго и Бена Уиллера
новинка? должен быть написан на Машинописи
и использование декораторов
ИЛИ статическое свойство / поле

import * as React from "react";
import Component = React.Component;
import { withRouter } from "react-router";

export interface INavigatorProps {
    router?: ReactRouter.History.History;
}

/**
 * Note: goes great with mobx 
 * @inject("something") @withRouter @observer
 */
@withRouter
export class Navigator extends Component<INavigatorProps, {}>{
    navigate: (to: string) => void;
    constructor(props: INavigatorProps) {
        super(props);
        let self = this;
        this.navigate = (to) => self.props.router.push(to);
    }
    render() {
        return (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

/**
 * Non decorated 
 */
export class Navigator2 extends Component<INavigatorProps, {}> {

    static contextTypes = {
        router: React.PropTypes.object.isRequired,
    };

    navigate: (to: string) => void;
    constructor(props: INavigatorProps, context: any) {
        super(props, context);
        let s = this;
        this.navigate = (to) =>
            s.context.router.push(to);
    }
    render() {
        return (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

С любым установленным сегодня npm. "response-router": "^ 3.0.0" и
"@ types / response-router": "^ 2.0.41"

12
David Schumann 26 Мар 2018 в 19:41

С появлением React-Router v4 на горизонте появился новый способ сделать это.

import { MemoryRouter, BrowserRouter } from 'react-router';

const navigator = global && global.navigator && global.navigator.userAgent;
const hasWindow = typeof window !== 'undefined';
const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1;
const Router = isBrowser ? BrowserRouter : MemoryRouter;

<Router location="/page-to-go-to"/>

react-lego - это пример приложения, которое показывает как использовать / обновить response-router и включает в себя примеры функциональных тестов для навигации по приложению.

14
peter.mouland 19 Апр 2018 в 11:53

Чтобы использовать withRouter с компонентом на основе классов, попробуйте что-то вроде этого ниже. Не забудьте изменить оператор экспорта на использование withRouter:

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

class YourClass extends React.Component {
  yourFunction = () => {
    doSomeAsyncAction(() =>
      this.props.history.push('/other_location')
    )
  }

  render() {
    return (
      <div>
        <Form onSubmit={ this.yourFunction } />
      </div>
    )
  }
}

export default withRouter(YourClass);
16
Janos 28 Май 2018 в 09:02

В React-Router v4 и ES6

Вы можете использовать withRouter и this.props.history.push.

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

class Home extends Component {

    componentDidMount() {
        this.props.history.push('/redirect-to');
    }
}

export default withRouter(Home);
19
Hossein 17 Окт 2017 в 07:35

Для компонентов ES6 + React у меня сработало следующее решение.

Я последовал за скиннером Фелиппе, но добавил комплексное решение, чтобы помочь таким новичкам, как я.

Ниже приведены версии, которые я использовал:

"реактивный маршрутизатор": "^ 2.7.0"

"реагировать": "^ 15.3.1"

Ниже приведен мой компонент реакции, в котором я использовал программную навигацию с помощью response-router:

import React from 'react';

class loginComp extends React.Component {
   constructor( context) {
    super(context);
    this.state = {
      uname: '',
      pwd: ''
    };
  }

  redirectToMainPage(){
        this.context.router.replace('/home');
  }

  render(){
    return <div>
           // skipping html code 
             <button onClick={this.redirectToMainPage.bind(this)}>Redirect</button>
    </div>;
  }
};

 loginComp.contextTypes = {
    router: React.PropTypes.object.isRequired
 }

 module.exports = loginComp;

Ниже представлена ​​конфигурация моего маршрутизатора:

 import { Router, Route, IndexRedirect, browserHistory } from 'react-router'

 render(<Router history={browserHistory}>
          <Route path='/' component={ParentComp}>
            <IndexRedirect to = "/login"/>
            <Route path='/login' component={LoginComp}/>
            <Route path='/home' component={HomeComp}/>
            <Route path='/repair' component={RepairJobComp} />
            <Route path='/service' component={ServiceJobComp} />
          </Route>
        </Router>, document.getElementById('root'));
20
Community 20 Июн 2020 в 09:12

Возможно, это не лучший подход, но ... Используя response-router v4, следующий Typescript может дать представление для некоторых.

В визуализированном компоненте ниже, например LoginPage, router объект доступен и просто вызовите router.transitionTo('/homepage') для навигации.

Код навигации был взят от.

"react-router": "^4.0.0-2", "react": "^15.3.1",

import Router from 'react-router/BrowserRouter';
import { History } from 'react-history/BrowserHistory';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();

interface MatchWithPropsInterface {
  component: typeof React.Component,
  router: Router,
  history: History,
  exactly?: any,
  pattern: string
}

class MatchWithProps extends React.Component<MatchWithPropsInterface,any> {
  render() {
    return(
      <Match {...this.props} render={(matchProps) => (
             React.createElement(this.props.component, this.props)

        )}
       />
    )
  }
}

ReactDOM.render(
    <Router>
      {({ router }) => (
        <div>
          <MatchWithProps exactly pattern="/" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/login" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/homepage" component={HomePage} router={router} history={history} />
          <Miss component={NotFoundView} />
        </div>
      )}
    </Router>,

   document.getElementById('app')
);
21
Rich Warrior 8 Авг 2019 в 17:53

Чтобы выполнить навигацию программно, вам нужно поместить новую историю в props.history в вашем component, чтобы что-то вроде этого могло сделать всю работу за вас. :

//using ES6
import React from 'react';

class App extends React.Component {

  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick(e) {
    e.preventDefault()
    /* Look at here, you can add it here */
    this.props.history.push('/redirected');
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          Redirect!!!
        </button>
      </div>
    )
  }
}

export default App;
24
David Schumann 26 Мар 2018 в 19:50

Я пробовал как минимум 10 способов сделать это, прежде чем что-то сработало правильно!

Ответ @Felipe Skinner withRouter меня немного ошеломил, и я не был уверен, что хочу создать новые имена классов "ExportedWithRouter".

Вот самый простой и понятный способ сделать это примерно в текущих React-Router 3.0.0 и ES6:

React-Router 3.x.x с ES6:

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
export default withRouter(Example);

Или, если это не ваш класс по умолчанию, экспортируйте, например:

withRouter(Example);
export { Example };

Обратите внимание, что в 3.x.x сам компонент <Link> использует router.push, поэтому вы можете передать ему все, что вы передаете тегу <Link to=, например:

   this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'
29
David Schumann 26 Мар 2018 в 18:38

Предупреждение: этот ответ относится только к версиям ReactRouter до 1.0.

Я обновлю этот ответ с помощью вариантов использования 1.0.0-rc1 после!

Вы можете сделать это и без миксинов.

let Authentication = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  handleClick(e) {
    e.preventDefault();
    this.context.router.transitionTo('/');
  },
  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

Проблема с контекстами заключается в том, что они недоступны, пока вы не определите contextTypes в классе.

Что касается контекста, то это объект, такой как свойства, который передается от родителя к дочернему, но передается неявно, без необходимости каждый раз повторно объявлять свойства. См. https: //www.tildedave. ru / 2014/11/15 / Introduction-to-context-in-react-js.html

33
Community 20 Июн 2020 в 09:12

РЕДАКТИРОВАТЬ: React Router v6

Я давно не касался React, но хочу поблагодарить и выделить комментарий @Shimrit Snapir ниже.

on React-Router 6.0 <Redirect /> changed to <Navigate />

React Router V4

ТЛ: д-р ;

if (navigate) {
  return <Redirect to="/" push={true} />
}

Простой и декларативный ответ заключается в том, что вам нужно использовать <Redirect to={URL} push={boolean} /> в сочетании с setState()

push: boolean - , когда true, перенаправление будет помещать новую запись в историю вместо замены текущей.


import { Redirect } from 'react-router'

class FooBar extends React.Component {
  state = {
    navigate: false
  }

  render() {
    const { navigate } = this.state
    
    // here is the important part
    if (navigate) {
      return <Redirect to="/" push={true} />
    }
   // ^^^^^^^^^^^^^^^^^^^^^^^
    
    return (
      <div>
        <button onClick={() => this.setState({ navigate: true })}>
          Home
        </button>
      </div>
    )
  }
}

Полный пример здесь. Дополнительные сведения см. здесь.

PS. В примере используется ES7 + Property Initializers для инициализации состояния. Если вам интересно, посмотрите здесь .

46
Lyubomir 22 Окт 2020 в 14:28

Для того, кто не контролирует серверную часть и из-за этого использует хэш-маршрутизатор v2:

Поместите свою историю в отдельный файл (например, app_history.js ES6):

import { useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });

export default appHistory;

И используйте его везде!

Ваша точка входа для реактивного маршрутизатора (app.js ES6):

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Redirect } from 'react-router'
import appHistory from './app_history'
...
const render((
  <Router history={appHistory}>
  ...
  </Router>
), document.querySelector('[data-role="app"]'));

Ваша навигация внутри любого компонента (ES6):

import appHistory from '../app_history'
...
ajaxLogin('/login', (err, data) => {
  if (err) {
    console.error(err); // login failed
  } else {
    // logged in
    appHistory.replace('/dashboard'); // or .push() if you don't need .replace()
  }
})
49
David Schumann 26 Мар 2018 в 17:29

Ответ React-Router 4.x:

С моей стороны, мне нравится иметь единственный объект истории, который я могу переносить даже вне компонентов. Мне нравится иметь один файл history.js, который я импортирую по запросу и просто манипулирую им.

Вам просто нужно изменить BrowserRouter на Router и указать свойство истории. Это ничего не меняет для вас, кроме того, что у вас есть собственный объект истории, которым вы можете манипулировать как хотите.

Вам необходимо установить history, библиотеку, используемую react-router.

Пример использования, обозначение ES6:

< Сильный > history.js

import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory()

BasicComponent.js

import React, { Component } from 'react';
import history from './history';

class BasicComponent extends Component {

    goToIndex(e){
        e.preventDefault();
        history.push('/');
    }

    render(){
        return <a href="#" onClick={this.goToIndex}>Previous</a>;
    }
}

ИЗМЕНИТЬ 16 апреля 2018 г .:

Если вам нужно перейти из компонента, который фактически визуализируется из компонента Route, вы также можете получить доступ к истории из свойств, например:

BasicComponent.js

import React, { Component } from 'react';

class BasicComponent extends Component {

    navigate(e){
        e.preventDefault();
        this.props.history.push('/url');
    }

    render(){
        return <a href="#" onClick={this.navigate}>Previous</a>;
    }
}
58
Eric Martin 16 Апр 2018 в 11:51

Вот как это сделать с помощью react-router v2.0.0 с помощью ES6. react-router отошел от миксинов.

import React from 'react';

export default class MyComponent extends React.Component {
  navigateToPage = () => {
    this.context.router.push('/my-route')
  };

  render() {
    return (
      <button onClick={this.navigateToPage}>Go!</button>
    );
  }
}

MyComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
}
59
David Schumann 26 Мар 2018 в 18:40

React-Router v2

Для самого последнего выпуска (v2.0.0-rc5) рекомендуемый метод навигации - прямое нажатие на синглтон истории. Вы можете увидеть это в действии в "Навигация вне компонентов"..

Соответствующий отрывок:

import { browserHistory } from 'react-router';
browserHistory.push('/some/path');

Если вы используете более новый API-интерфейс реактивного маршрутизатора, вам необходимо использовать history из this.props внутри компонентов, поэтому:

this.props.history.push('/some/path');

Он также предлагает pushState, но он устарел из-за зарегистрированных предупреждений.

При использовании react-router-redux он предлагает функцию push, которую вы можете отправить следующим образом:

import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));

Однако это можно использовать только для изменения URL-адреса, а не для фактического перехода на страницу.

517
David Schumann 26 Мар 2018 в 18:50

React-Router 5.1.0+ Ответ (с использованием хуков и React> 16.8)

Вы можете использовать новый крючок useHistory для функциональных компонентов и программной навигации:

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

function HomeButton() {
  let history = useHistory();
  // use history.push('/some/path') here
};

React-Router 4.0.0+ Ответ

В версии 4.0 и выше используйте историю как опору вашего компонента.

class Example extends React.Component {
   // use `this.props.history.push('/some/path')` here
};

ПРИМЕЧАНИЕ: this.props.history не существует в случае, если ваш компонент не был отрисован с помощью <Route>. Вы должны использовать <Route path="..." component={YourComponent}/>, чтобы this.props.history был в YourComponent

React-Router 3.0.0+ Ответ

В версии 3.0 и выше используйте маршрутизатор в качестве опоры вашего компонента.

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

React-Router 2.4.0+ Ответ

В версии 2.4 и выше используйте компонент более высокого порядка, чтобы маршрутизатор стал опорой вашего компонента.

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
var DecoratedExample = withRouter(Example);

// PropTypes
Example.propTypes = {
  router: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  }).isRequired
};

React-Router 2.0.0+ Ответ

Эта версия обратно совместима с 1.x, поэтому нет необходимости в Руководстве по обновлению. Достаточно просто просмотреть примеры.

Тем не менее, если вы хотите переключиться на новый шаблон, внутри маршрутизатора есть модуль browserHistory, к которому вы можете получить доступ с помощью

import { browserHistory } from 'react-router'

Теперь у вас есть доступ к истории браузера, поэтому вы можете выполнять такие действия, как push, замена и т. Д. Например:

browserHistory.push('/some/path')

Дальнейшее чтение: Истории и Навигация


React-Router 1.x.x Ответ

Я не буду вдаваться в подробности обновления. Вы можете прочитать об этом в Руководстве по обновлению

Основное изменение в вопросе здесь - это переход от примеси навигации к истории. Теперь он использует API истории браузера для изменения маршрута, поэтому с этого момента мы будем использовать pushState().

Вот пример использования Mixin:

var Example = React.createClass({
  mixins: [ History ],
  navigateToHelpPage () {
    this.history.pushState(null, `/help`);
  }
})

Обратите внимание, что этот History взят из проекта Rackt / history. Не из самого React-Router.

Если вы по какой-то причине не хотите использовать Mixin (возможно, из-за класса ES6), вы можете получить доступ к истории, которую вы получаете от маршрутизатора, из this.props.history. Он будет доступен только для компонентов, отображаемых вашим маршрутизатором. Итак, если вы хотите использовать его в каких-либо дочерних компонентах, его необходимо передать как атрибут через props.

Вы можете узнать больше о новом выпуске в их документации 1.0.x

Вот справочная страница, посвященная навигации за пределами ваш компонент

Он рекомендует взять ссылку history = createHistory() и вызвать replaceState по ней.

React-Router 0.13.x Ответ

Я столкнулся с той же проблемой и смог найти решение только с помощью миксина Navigation, который поставляется с response-router.

Вот как я это сделал

import React from 'react';
import {Navigation} from 'react-router';

let Authentication = React.createClass({
  mixins: [Navigation],

  handleClick(e) {
    e.preventDefault();

    this.transitionTo('/');
  },

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

Мне удалось позвонить transitionTo() без доступа к .context

Или вы можете попробовать необычный ES6 class

import React from 'react';

export default class Authentication extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e) {
    e.preventDefault();

    this.context.router.transitionTo('/');
  }

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
}

Authentication.contextTypes = {
  router: React.PropTypes.func.isRequired
};

React-Router-Redux

Примечание. если вы используете Redux, есть еще один проект под названием React-Router-Redux, который дает вам redux для ReactRouter, используя тот же подход, что и React-Redux делает

React-Router-Redux имеет несколько доступных методов, которые позволяют легко перемещаться изнутри создателей действий. Это может быть особенно полезно для людей, у которых уже есть архитектура в React Native, и они хотят использовать те же шаблоны в React Web с минимальными накладными расходами.

Изучите следующие методы:

  • push(location)
  • replace(location)
  • go(number)
  • goBack()
  • goForward()

Вот пример использования с Redux-Thunk:

./actioncreators.js

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

export const onBackPress = () => (dispatch) => dispatch(goBack())

./viewcomponent.js

<button
  disabled={submitting}
  className="cancel_button"
  onClick={(e) => {
    e.preventDefault()
    this.props.onBackPress()
  }}
>
  CANCEL
</button>
974
IronSean 18 Окт 2019 в 17:44

Программная навигация в компонентах на основе классов.

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

class MyComponent extends React.Component{
    state= {rpath: null}

    const goTo= (path)=> this.setState({rpath: path});

    render(){
        if(this.state.rpath){
            return <Redirect to={this.state.rpath}/>
        }
        .....
        .....
    }
}

Надеюсь, это поможет.

3
shivampip 15 Сен 2020 в 06:28

Вместо этого попробуйте hookrouter, «современную альтернативу response-router».

https://www.npmjs.com/package/hookrouter

import { useRoutes, usePath, A} from "hookrouter";

Чтобы ответить на вопрос OP о связывании через поле выбора, вы можете сделать это:

navigate('/about');

*** ОБНОВЛЕННЫЙ ОТВЕТ ***

Я думаю, что hook-router был хорошим стартовым комплектом и помог мне узнать о маршрутизации, но с тех пор обновлен до response-router для его истории и обработки параметров запроса.

import { useLocation, useHistory } from 'react-router-dom';


const Component = (props) => {
    const history = useHistory();
    
    // Programmatically navigate
    history.push(newUrlString);
}

Вы нажимаете туда, куда хотите перейти в location.history.

3
StefanBob 10 Сен 2020 в 00:51

Это сработало для меня, никакого специального импорта не требуется:

<input 
  type="button" 
  name="back" 
  id="back" 
  class="btn btn-primary" 
  value="Back" 
  onClick={() => { this.props.history.goBack() }} 
/>
3
ravibagul91 15 Сен 2019 в 09:45

Если произойдет соединение RR4 с redux через реагирующий маршрутизатор -redux, также можно использовать средства создания действий маршрутизации из react-router-redux.

import { push, replace, ... } from 'react-router-redux'

class WrappedComponent extends React.Component {
  handleRedirect(url, replaceState = true) { 
    replaceState 
      ? this.props.dispatch(replace(url)) 
      : this.props.dispatch(push(url)) 
  }
  render() { ... }
}

export default connect(null)(WrappedComponent)

Если вы используете redux thunk / saga для управления асинхронным потоком, импортируйте вышеуказанные создатели действий в redux actions и подключите реагирующие компоненты с помощью mapDispatchToProps.

4
Xlee 7 Май 2018 в 06:43

Возможно, не лучшее решение, но оно выполняет свою работу:

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

// create functional component Post
export default Post = () => (
    <div className="component post">

        <button className="button delete-post" onClick={() => {
            // ... delete post
            // then redirect, without page reload, by triggering a hidden Link
            document.querySelector('.trigger.go-home').click();
        }}>Delete Post</button>

        <Link to="/" className="trigger go-home hidden"></Link>

    </div>
);

По сути, логика, привязанная к одному действию (в данном случае удаление записи), в конечном итоге вызывает триггер для перенаправления. Это не идеально, потому что вы добавите в разметку «триггер» узла DOM, чтобы его можно было удобно вызывать при необходимости. Кроме того, вы будете напрямую взаимодействовать с DOM, что может быть нежелательно в компоненте React.

Тем не менее, этот тип перенаправления требуется не так часто. Таким образом, одна или две дополнительные скрытые ссылки в разметке вашего компонента не повредят, особенно если вы дадите им осмысленные имена.

4
David Schumann 27 Мар 2018 в 11:50

Правильный ответ был для меня на момент написания

this.context.router.history.push('/');

Но вам нужно добавить PropTypes в свой компонент

Header.contextTypes = {
  router: PropTypes.object.isRequired
}
export default Header;

Не забудьте импортировать PropTypes

import PropTypes from 'prop-types';
4
David Schumann 27 Мар 2018 в 11:44

Обновление: React Router v6 с хуками

import {useNavigate} from 'react-router-dom';
let navigate = useNavigate();
navigate('home');

И чтобы перемещаться по истории браузера,

navigate(-1); ---> Go back
navigate(1);  ---> Go forward
navigate(-2); ---> Move two steps backward.
5
Vijay122 18 Июн 2020 в 14:56

Вы также можете использовать ловушку useHistory в компоненте без сохранения состояния. . Пример из документации.

import { useHistory } from "react-router"

function HomeButton() {
  const history = useHistory()

  return (
    <button type="button" onClick={() => history.push("/home")}>
      Go home
    </button>
  )
}

Примечание. Хуки были добавлены в react-router@5.1.0 и требуют react@>=16.8

6
Nickofthyme 7 Окт 2019 в 17:38

Те, кто сталкивается с проблемами при реализации этого на react-router v4.

Вот рабочее решение для навигации по приложению реакции из действий redux.

History.js

import createHistory from 'history/createBrowserHistory'

export default createHistory()

App.js / Route.jsx

import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
 <Route path="/test" component={Test}/>
</Router>

Another_file.js ИЛИ файл redux

import history from './history' 

history.push('/test') // this should change the url and re-render Test component

Все благодаря этому комментарию: Комментарий по проблемам ReactTraining

6
Moshe Slavin 31 Мар 2019 в 15:25