Як отримати історію на response-router v4?


101

У мене є невелика проблема з переходом з React-Router v3 на v4. у v3 я міг зробити це де завгодно:

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

Як мені досягти цього у v4.

Я знаю, що я міг би використовувати hoc withRouter, контекст реакції або реквізити маршрутизатора подій, коли ви знаходитесь у Component. але це не так для мене.

Я шукаю еквівалентність NavigatingOutsideOfComponents у v4


1
Дякую @Chris, але, як я вже сказав, я не в Component.
storm_buster

@Chris у класі утиліти, будь ласка, перевірте github.com/ReactTraining/react-router/blob/master/docs/guides/… , це могло бути відновлене проміжне програмне забезпечення або щось інше
storm_buster

Найпростіший спосіб stackoverflow.com/a/53916596/3966458
Saahithyan Vigneswaran

У підсумку я використав BrowserRouter як кореневий компонент. Таким чином я міг використовувати компонент App withRouter. Не зовсім те, про що ви просили, але у мене ті самі вимоги, і цього мені достатньо.
Дурень,

Відповіді:


180

Вам просто потрібно мати модуль, який експортує historyоб’єкт. Тоді ви імпортували б цей об’єкт протягом усього проекту.

// history.js
import { createBrowserHistory } from 'history'

export default createBrowserHistory({
  /* pass a configuration object here if needed */
})

Потім, замість того, щоб використовувати один із вбудованих маршрутизаторів, ви б використовували <Router>компонент.

// index.js
import { Router } from 'react-router-dom'
import history from './history'
import App from './App'

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder)
// some-other-file.js
import history from './history'
history.push('/go-here')

1
Дуже дякую! На даний момент, використовуючи response-router4, мені довелося замість цього використати цей імпорт у history.js: import createBrowserHistory з 'history / createBrowserHistory';
peter.bartos

3
У мене це спрацювало, коли я кладу історію = {історію} в Маршрут і проходжу як реквізит
Натх Пайва

1
ми можемо використовувати withHistory та отримувати історію в реквізиті, а не створювати окремий файл. це рішення не працювало для мене з redux.
Zeel Shah

4
Імпортуйте, createHashHistoryякщо ви використовували HashRouter.
Девід Харкнес,

2
@HassanAzzam Ви, мабуть, використовуєте реакційний маршрутизатор V5, і ця відповідь працює для V4, а не V5. Зараз у мене такий самий виклик, і я шукаю його всюди, але не можу змусити це працювати. history.push поза компонентом працює, але натискання на посилання більше не робить.
Waterlink

71

Це працює! https://reacttraining.com/react-router/web/api/withRouter

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

class MyComponent extends React.Component {
  render () {
    this.props.history;
  }
}

withRouter(MyComponent);

27
поки ви перебуваєте в складовій. Я не в компоненті
storm_buster

1
Дякую, це найпростіший і найпростіший спосіб зв’язати інший маршрут із компонента. Я б лише додав, що вам потрібно це зробити this.props.history.push('/some_route');, щоб це спрацювало.
dannytenaglias

1
@storm_buster const Component = props => {... // stuff}і export default withRouter(Component)працює для мене над компонентом без громадянства
Карл Тейлор

10

Подібно до прийнятої відповіді, що ви могли б зробити, це використовувати reactі react-routerсаме надавати вамhistory об'єкт, який ви можете розмістити у файлі, а потім експортувати.

history.js

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

// variable which will point to react-router history
let globalHistory = null;

// component which we will mount on top of the app
class Spy extends React.Component {
  constructor(props) {
    super(props)
    globalHistory = props.history; 
  }

  componentDidUpdate() {
    globalHistory = this.props.history;
  }

  render(){
    return null;
  }
}

export const GlobalHistory = withRouter(Spy);

// export react-router history
export default function getHistory() {    
  return globalHistory;
}

Потім ви імпортуєте Component і mount для ініціалізації змінної історії:

import { BrowserRouter } from 'react-router-dom';
import { GlobalHistory } from './history';

function render() {
  ReactDOM.render(
    <BrowserRouter>
        <div>
            <GlobalHistory />
            //.....
        </div>
    </BrowserRouter>
    document.getElementById('app'),
  );
}

А потім ви можете просто імпортувати у свою програму, коли її встановлено:

import getHistory from './history'; 

export const goToPage = () => (dispatch) => {
  dispatch({ type: GO_TO_SUCCESS_PAGE });
  getHistory().push('/success'); // at this point component probably has been mounted and we can safely get `history`
};

Я навіть зробив і пакет npm, який робить саме це.


Починаючи з responsejs 16.9, це рішення буде видавати попередження про припинення дії на componentWillMount і componentWillReceiveProps.
Ян

1
@ian правда, це виправлено
Томаш Муларчик

5

Якщо ви використовуєте redux і redux-thunk, найкращим рішенням буде використання response-router-redux

// then, in redux actions for example
import { push } from 'react-router-redux'

dispatch(push('/some/path'))

Важливо переглянути документи, щоб виконати деякі конфігурації.


1
Я прийшов сюди, сподіваючись знайти саме це рішення, дякую
vapurrmaid

4

Виходячи з цієї відповіді, якщо вам потрібен об’єкт історії лише для переходу до іншого компонента:

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

НЕПРАВИЛЬНО, ви знаходитесь всередині компонента. див. // some-other-file.js із прийнятої відповіді
storm_buster

0

У App.js

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

 const TheContext = React.createContext(null);

 const App = () => {
   const history = useHistory();

   <TheContext.Provider value={{ history, user }}>

    <Switch>
        <Route exact path="/" render={(props) => <Home {...props} />} />
        <Route
          exact
          path="/sign-up"
          render={(props) => <SignUp {...props} setUser={setUser} />}
        /> ...

Тоді в дочірньому компоненті:

const Welcome = () => {
    
    const {user, history} = React.useContext(TheContext); 
    ....

-2

У конкретному випадку react-router, використання contextє дійсним сценарієм випадку, наприклад

class MyComponent extends React.Component {
  props: PropsType;

  static contextTypes = {
    router: PropTypes.object
  };

  render () {
    this.context.router;
  }
}

Ви можете отримати доступ до екземпляра історії через контекст маршрутизатора, наприклад this.context.router.history.


Питання конкретно задає питання про те, коли поза компонентом, тому this.context недоступний як опція:> "Я знаю, що я міг би використовувати, hoc withRouter, контекст реакції або маршрутизатор подій, коли ви знаходитесь у Компоненті. Але це не так для мене ".
SunshinyDoyle
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.