react-router v4の履歴を取得する方法は?


100

React-Router v3からv4への移行に少し問題があります。v3では、どこでもこれを行うことができました。

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

これをv4で実現するにはどうすればよいですか。

withRouterあなたがコンポーネントにいるとき、私はその場で、反応コンテキスト、またはイベントルーターの小道具を使用できることを知っています。しかし、それは私には当てはまりません。

私はv4 のNavigatingOutsideOfComponentsと同等のものを探しています


1
@Chrisに感謝しますが、私が言ったように、私はComponentではありません。
storm_buster 2017年

@Chrisはユーティリティクラスです。github.com/ ReactTraining / react-router / blob / master / docs / guides /…を確認してください。これは、reduxミドルウェアまたはその他の何かである可能性があります
storm_buster


私はBrowserRouterをルートコンポーネントとして使用することになりました。そうすれば、RouterでAppコンポーネントを使用できます。あなたが要求したとおりではありませんが、私は同じ要件を持っているので、これで十分です。
フール

回答:


179

historyオブジェクトをエクスポートするモジュールが必要です。次に、そのオブジェクトをプロジェクト全体にインポートします。

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

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

次に、組み込みルーターの1つを使用する代わりに、<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
どうもありがとう!現時点では、react-router4を使用して、代わりにこのインポートをhistory.jsで使用する必要がありました。
peter.bartos

3
ルートにhistory = {history}を入れて小道具のように渡すとうまくいきました
Nath Paiva

1
別のファイルを作成するのではなく、withHistoryを使用して、小道具の履歴を取得できます。このソリューションは、reduxでは私にとってうまくいきませんでした。
Zeel Shah 2017

4
createHashHistoryを使用していHashRouterた場合はインポートします。
デビッド・ハークネス2017

2
@HassanAzzam反応ルーターV5を使用している可能性があり、この回答はV5ではなくV4で機能します。私は今、同じ課題を抱えており、あらゆる場所を探していますが、それを機能させることができません。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);

26
コンポーネント内にいる限り。私はコンポーネントではありません
storm_buster 2017年

1
これは、コンポーネントから別のルートにリンクする最も簡単で簡単な方法です。それが機能this.props.history.push('/some_route');するためにあなたがしなければならないことを追加します。
dannytenaglias 2017

1
@storm_buster const Component = props => {... // stuff}export default withRouter(Component)ステートレスコンポーネントで私のために働く
カールテイラー

10

あなたができることを受け入れられた答えの似たようなものはreactreact-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;
}

その後、コンポーネントをインポートし、マウントして履歴変数を初期化します。

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パッケージを作成しました。


reactjs 16.9以降、このソリューションは、componentWillMountおよびcomponentWillReceivePropsで非推奨の警告を出力します。
イアン

1
@ian true、修正済み
Tomasz Mularczyk

5

reduxとredux-thunkを使用している場合、最適なソリューションは、react-router-reduxを使用することです。

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

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

いくつかの構成を行うには、ドキュメントを参照することが重要です。


1
私はこの正確な解決策を見つけたいと思ってここに来ました、ありがとう
vapurrmaid '28 / 02/28

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はオプションとして利用できません。>「私は、コンポーネントにいるときに、ホックwithRouter、リアクションコンテキスト、またはイベントルータープロップを使用できることを知っています。それは私には当てはまりません。」
SunshinyDoyle 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.