Программно перемещаться с помощью реагирующего маршрутизатора

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

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

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

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

Ответ 1

React Router v5.1.0 with hooks

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

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

function HomeButton() {
  let 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, но в версии 4 компоненты <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. Используйте контекст *

Но вы, вероятно, не должны

Последний вариант - тот, который вам следует использовать, только если вы чувствуете себя комфортно при работе с моделью Rea context. Хотя контекст является опцией, следует подчеркнуть, что контекст - это нестабильный API, и в документации React есть раздел Почему бы не использовать контекст. Так что используйте на свой страх и риск!

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 - самый простой вариант реализации, поэтому в большинстве случаев они являются вашими лучшими ставками.

Ответ 2

React-Router 5.1.0+ Answer (using hooks и 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+ Answer

В версии 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+ Answer

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

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

React-Router 2.4.0+ Answer

В версии 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+ Answer

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

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

import { browserHistory } from 'react-router'

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

browserHistory.push('/some/path')

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


React-Router 1.x.x Answer

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

.Основное изменение в этом вопросе - это переход от Mixin навигации к истории. Теперь он использует браузер historyAPI для изменения маршрута, поэтому теперь мы будем использовать 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 Answer

Я попал в ту же проблему и смог найти решение только с помощью навигационного миксина, поставляемого с реагирующим маршрутизатором.

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

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, который дает вам редукционные привязки для 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>

Ответ 3

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, а не для перехода на страницу.

Ответ 4

Вот как вы делаете это с 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
}

Ответ 5

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

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

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

Вам нужно установить историю, библиотеку, которую использует 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>;
    }
}

Ответ 6

Для этого, кто не контролирует серверную часть и из-за этого использует hash router 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()
  }
})

Ответ 7

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+ для инициализации состояния. Посмотри здесь, если тебе интересно.

Ответ 8

Предупреждение: этот ответ охватывает только версии 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.com/2014/11/15/introduction-to-contexts-in-react-js.html.

Ответ 9

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

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

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

React-Router 3.xx с 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.xx сам компонент <Link> использует router.push, поэтому вы можете передавать его как угодно, передавая <Link to=, например:

   this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'

Ответ 10

Чтобы выполнить навигацию программно, вам нужно добавить новую историю в 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;

Ответ 11

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

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

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

"response-router": "^ 2.7.0"

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

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

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

Ответ 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')
);

Ответ 13

Ниже приведен рабочий код: Как уже говорилось в этой статье, это очень простой способ навигации с использованием реагирующего маршрутизатора:

class Register extends React.Component {
  state = {
    toDashboard: false,
  }
  handleSubmit = (user) => {
    saveUser(user)
      .then(() => this.setState(() => ({
        toDashboard: true
      })))
  }
  render() {
    if (this.state.toDashboard === true) {
      return <Redirect to='/dashboard' />
    }

    return (
      <div>
        <h1>Register</h1>
        <Form onSubmit={this.handleSubmit} />
      </div>
    )
  }
}

< Redirect/> есть

Композитный ✅ Декларативный ✅ Пользовательское событие → Изменение состояния → Повторная визуализация ✅

Компонент Register обрабатывается React Router, наш код может выглядеть следующим образом

class Register extends React.Component {
  handleSubmit = (user) => {
    saveUser(user).then(() =>
      this.props.history.push('/dashboard')
    ))
  }
  render() {
    return (
      <div>
        <h1>Register</h1>
        <Form onSubmit={this.handleSubmit} />
      </div>
    )
  }
}

добавив withRouter, это будет выглядеть так

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

class Register extends React.Component {
  handleSubmit = (user) => {
    saveUser(user).then(() =>
      this.props.history.push('/dashboard')
    ))
  }
  render() {
    return (
      <div>
        <h1>Register</h1>
        <Form onSubmit={this.handleSubmit} />
      </div>
    )
  }
}

export default withRouter(Register)

Существует два способа программной навигации с помощью React Router - и history.push. То, что вы используете, в основном зависит от вас и вашего конкретного случая использования, хотя я стараюсь отдавать предпочтение Redirect.

Ответ 14

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

Ответ 15

Чтобы использовать 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

с 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"/>

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

Ответ 17

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

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/реакции-маршрутизатор": "^ 2.0.41"

Ответ 18

В реакции роутера v4. Я следую этому двухстороннему маршруту программно.

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

Номер два

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

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

withRouter

Ответ 19

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

hashHistory.push('/login');
browserHistory.push('/login');

Ответ 20

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

browser.js: 49 Предупреждение: [ props.history -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;

Ответ 21

React-Router V4

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

dispatch(navigateTo("/aboutUs"));

trippler

Ответ 22

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

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

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 ИЛИ редукционный файл

import history from './history' 

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

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

Ответ 23

Если случится с парой RR4 с редуктом через response -router-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 и подключайте для реагирования компоненты, используя mapDispatchToProps.

Ответ 24

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

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 может быть нежелательно.

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

Ответ 25

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

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

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

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

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

import PropTypes from 'prop-types';

Ответ 26

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

import { useHistory } from "react-router"

function HomeButton() {
  const history = useHistory()

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

Note: Hooks were added in [email protected] и require [email protected]>=16.8

Ответ 27

Это сработало для меня, нет необходимости в специальном импорте:

<input 
  type="button" 
  name="back" 
  id="back" 
  class="btn btn-primary" 
  value="Back" 
  onClick={() => { this.props.history.goBack() }} 
/>

Ответ 28

Для React Router v4+

Предполагая, что вам не нужно будет перемещаться во время самого начального рендеринга (для которого вы можете использовать компонент <Redirect>), это то, что мы делаем в нашем приложении.

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

Теперь вы можете делать все, что можно сделать в истории, например history.push(), history.replace(), history.go(-1) т.д.!

import React from 'react';
import { HashRouter, Route } from 'react-router-dom';

let routeHistory = null;

export function navigateTo(path) {
  if(routeHistory !== null) {
    routeHistory.push(path);
  }
}

export default function App(props) {
  return (
    <HashRouter hashType="noslash">
      <Route
        render={({ history }) => {
          routeHistory = history;
          return null;
        }}
      />
      {/* Rest of the App */}
    </HashRouter>
  );
}

Ответ 29

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

toProfile() {
   this.context.history.pushState(null, 'profile');
}

и добавьте функцию onClick

<li onClick={this.toProfile.bind(this)></li>

надеюсь, что это полезно для вас.

Ответ 30

В зависимости от , где вы хотите перенаправить. Если внутри компонента, то ответ @Paul S - лучший способ сделать это.

Но если вы хотите перенаправить из любого места внутри приложения, я рекомендую использовать react-router-redux