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

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

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

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

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

Комментарии к вопросу (6)
Решение

React Router v5.1.0 с крючками

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

      Go home

  );
}

React Router v4

С v4 React Router есть три подхода, которые вы можете использовать для программной маршрутизации внутри компонентов.

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

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

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

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

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

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

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

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

))

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

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

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

const Button = () => (
   (
     { history.push('/new-location') }}
    >
      Click Me!

  )} />
)

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

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

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

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

)

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

& Лт; br / > Кроме того, вы можете получить больше знаний по нижним ссылкам о маршрутизации, параметрах URL и вложенной маршрутизации.

Маршрутизация в React JS < br / >

  • Пошаговое объяснение того, как интегрировать реактивный маршрутизатор в ReactJS

Параметры URL с помощью React Router < br / >

  • Здесь вы можете получить представление о том, как установить параметры URL с помощью React Router. Основное использование маршрутизации параметров URL - визуализация одного и того же компонента на основе его динамического URL.

Вложенные маршруты в React JS < br / >

  • Если вы хотите загрузить субмаршруты по основным маршрутам, вам нужно создать вложенные маршруты. Вот живой пример этого.

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

Комментарии (14)

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 >. Вы должны использовать < Маршрут пути = "..."component = {YourComponent} / > иметь этот.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} из 'react-router'

Теперь у вас есть доступ к истории вашего браузера, поэтому вы можете делать такие вещи, как push, map и т. Д... Подобно:

browserHistory.push ('/ some/path')

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


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

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

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

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

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

Обратите внимание, что эта «История» происходит из проекта rackt / history. Не от самого React-Router.

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

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

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

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

React-Router 0.13.x Ответ

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

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

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 (местоположение)
  • заменить (местоположение)
  • go (число)
  • GoBack ()
  • goForward ()

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

./actioncreators.js

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

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

./viewcomponent.js

 {
    e.preventDefault()
    this.props.onBackPress()
  }}
>
  CANCEL
Комментарии (13)

React-Router v2

Для самого последнего выпуска (v2.0.0-rc5) рекомендуемый метод навигации заключается в непосредственном переходе к истории синглтон. Вы можете видеть это в действии в < a href = "https://github.com/rackt/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md"> Навигация вне компонентов doc < / a >.

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

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

При использовании более нового API-интерфейса react-router вам необходимо использовать 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-адреса, а не для перехода на страницу.

Комментарии (14)

Вот как вы делаете это с react-router v2.0.0 с [ES6] ( http://babeljs.io/blog/2015/06/07/reacton. «Реактивный роутер» отошел от миксинов.

import React from 'react';

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

  render() {
    return (
      Go!
    );
  }
}

MyComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
}
Комментарии (2)

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

EDIT 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>;
    }
}
Комментарии (2)

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

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

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

export default appHistory;

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

Ваша точка входа для react-router (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((

  ...

), 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()
  }
})
Комментарии (5)

React Router V4

tl: dr ;

if (navigate) {
  return 
}

Простой и декларативный ответ заключается в том, что вам нужно использовать < Перенаправить на = {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 
    }
   // ^^^^^^^^^^^^^^^^^^^^^^^

    return (
      <div>
         this.setState({ navigate: true })}>
          Home

      </div>
    )
  }
}

Полный пример здесь. Читать дальше здесь.

PS. В примере используется ES7 + Инициализаторы свойств для инициализации состояния. Посмотрите здесь, если вам интересно.

Комментарии (3)

Предупреждение: этот ответ охватывает только версии 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

Комментарии (0)

Я попробовал как минимум 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'})'
Комментарии (3)

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

          Redirect!!!

      </div>
    )
  }
}

export default App;
Комментарии (1)

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

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

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

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

& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >

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 {
  render() {
    return(
       (
             React.createElement(this.props.component, this.props)

        )}
       />
    )
  }
}

ReactDOM.render(

      {({ router }) => (
        <div>




        </div>
      )}
    ,

   document.getElementById('app')
);

& Лт;!- конец фрагмента - >

Комментарии (4)

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

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

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

«Реактивный роутер»: «^ 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 
             Redirect
    </div>;
  }
};

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

 module.exports = loginComp;

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

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

 render(







        , document.getElementById('root'));
Комментарии (0)

В 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);
Комментарии (1)

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

import {withRouter} из 'react-router-dom'

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

  render() {
    return (
      <div>

      </div>
    )
  }
}

export default withRouter(YourClass);
Комментарии (0)

на основании предыдущего ответа от Jos & # 233; Антонио Постиго и Бен Уилер новинка? должен быть написан на 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{
    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 {

    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, установленным сегодня. "react-router": "^ 3.0.0" и "@ types / react-router": "^ 2.0.41"

Комментарии (0)

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

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

Номер два

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

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

Комментарии (0)

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

react-lego - это пример приложения, который показывает [как использовать / обновить react-router](https://github.com/peter- mouland / react-lego/compare/react-router-4) и включает в себя примеры функциональных тестов, которые перемещаются в приложении.

Комментарии (1)

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

hashHistory.push('/login');
browserHistory.push('/login');
Комментарии (3)

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

browser.js: 49 Предупреждение: [react-router] props.history and 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;
Комментарии (1)

React-Router V4

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

dispatch(navigateTo("/aboutUs"));

Трипплер

Комментарии (0)