反応ルーターを使用してプログラムでナビゲートする


1431

react-router私は使用することができますLinkネイティブにルータを反応させることにより、処理されたリンクを作成する要素を。

私は内部的にそれが呼び出すのを見ますthis.context.transitionTo(...)

ナビをしたい。リンクからではなく、ドロップダウン選択から(例として)。コードでこれを行うにはどうすればよいですか?なにthis.context

Navigationミックスインを見ましたが、これなしでできmixinsますか?


26
@SergioTapiaは、この質問が、react-routerのメジャーリリース、Reactのメジャーリリース、およびjavascriptのメジャーリリースにまたがることを覚えておいてください
George Mauer

5
これは、react router v4の公式ドキュメントのチュートリアルへのリンクです:reacttraining.com/react-router/web/guides/scroll-restoration
chitzui

4
あなたはこの回答チェックすることができstackoverflow.com/questions/44127739/...
Shubhamカトリ

4
あなたがこれを答えてくれてうれしいですが、私はそれがこれほど複雑である必要があるのは悲しいです。Webアプリ内の移動は簡単で、十分に文書化されている必要があります。VueJSはそれを簡単にします。各コンポーネントは、ルーターインスタンスを自動的に挿入します。彼らのドキュメントには明確に定義されたセクションがあります。 router.vuejs.org/guide/essentials/navigation.html私は多くのことでReactが好きですが、ときどき非常に複雑です。</ rant>
colefner、

7
@GeorgeMauerそうですね。それがこのコミュニティの目的ではありません。それは質問に答えることに関するものであり、フレームワークについて争うことではありません。念押し有難う。
担当者、

回答:


1435

React Router v5.1.0とフック

useHistoryReact> 16.8.0と機能コンポーネントを使用している場合、React Router> 5.1.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

React Routerのv4では、コンポーネント内でプログラムによるルーティングを行うために使用できる3つのアプローチがあります。

  1. withRouter高次成分を使用してください。
  2. コンポジションを使用してレンダリングする <Route>
  3. を使用しcontextます。

React Routerは、主にhistoryライブラリのラッパーです。ブラウザとハッシュ履歴を使用して、ブラウザとhistoryのやり取りを処理window.historyします。また、グローバル履歴がない環境で役立つメモリ履歴も提供します。これは、モバイルアプリ開発(react-native)およびNodeを使用したユニットテストでます。

historyインスタンスがナビゲートするための2つのメソッドがありますpushreplacehistoryを訪問済みの場所の配列と考える場合、は配列にpush新しい場所を追加し、配列replace内の現在の場所を新しい場所に置き換えます。通常は、pushは、ナビゲートしているときにメソッドます。

ルータに反応の以前のバージョンでは、あなた自身の作成しなければならなかった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のコンテキストモデルの操作に慣れている場合にのみ使用するオプションです(ReactのContext APIは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は実装するのが最も簡単な選択肢であるため、ほとんどのユースケースでは、これらが最善の策です。


24
この方法でメソッド1を使用しようとしましたwithRouter(({history})=> {console.log( "hhhhhhhh"); history.push( '/ bets')}); しかし、ルーター4では機能しませんでした
Dmitry Malugin 2017年

57
何!?すべてのコンポーネントをパススルーするwithRouter代わりに使用できhistoryますか?私はもっ​​とドキュメントを読むためにもっと時間を費やす必要があります...
hellojeffhall 2017

18
history.push('/new-location')その動作をボタンや他のDOM要素に関連付けずに実行するにはどうすればよいですか?
Neil

4
エラーのスローUnexpected use of 'history' no-restricted-globals
Pardeep Jain

18
context反応16
以降

921

React-Router 5.1.0+ Answer(フックと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}/>YourComponentにthis.props.historyを含めるために使用する必要があります

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'

これでブラウザの履歴にアクセスできるようになり、プッシュ、置換などを実行できるようになりました。

browserHistory.push('/some/path')

参考資料履歴ナビゲーション


React-Router 1.xx回答

アップグレードの詳細には触れません。あなたはそれについて読むことができますアップグレードガイドで

ここでの質問に関する主な変更は、ナビゲーションミックスインから履歴への変更です。これで、ブラウザのhistoryAPIを使用してルートを変更しているので、pushState()します。

Mixinを使用した例を次に示します。

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

これHistoryラケット/歴史から来ていることに注意してくださいプロジェクト。React-Router自体からではありません。

何らかの理由で(おそらくES6クラスが原因で)Mixinを使用したくない場合は、からルーターから取得した履歴にアクセスできますthis.props.history。ルーターによってレンダリングされたコンポーネントからのみアクセスできます。したがって、子コンポーネントで使用したい場合は、属性として次のように渡す必要があります。props

あなたは彼らの新しいリリースについてもっと読むことができます 1.0.xのドキュメントを

ここは 、コンポーネントの外への移動に関するヘルプページです。

参照history = createHistory()を取得replaceStateして呼び出すことをお勧めします。

React-Router 0.13.xの回答

私は同じ問題に遭遇し、react-routerに付属するNavigationミックスインでのみ解決策を見つけることができました。

これが私がやった方法です

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のを使用している場合、と呼ばれる別のプロジェクトがあり ReactRouter-Reduxのあなたは多少同じアプローチ使用して、ReactRouterのバインディングをReduxの与え リアクト- 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
私が使用していますv2.4.0が、上記のアプローチは、私のために仕事をしません、私のアプリは、すべてのコンソール出力でレンダリングされません。Uncaught TypeError: (0 , _reactRouter.withRouter) is not a functionここに私のSOの記事へのリンクがあります:stackoverflow.com/questions/37306166/...
nburk

7
これは受け入れられる答えである必要があります。受け入れられるものは少し混乱しており、非常に古いです。@GiantElkバージョンの回答に記載されているように機能しています2.6.0
JMac 2016

2
このアプローチはまだバージョンの推奨方法3.0.xですか?多くの人がこのcontext方法を使用しているようです。
velop

6
4.0では、this.props.historyは存在しません。何が起こっている?
Nicolas S.Xu

4
@ NicolasS.Xu this.props.historyは、コンポーネントがによってレンダリングされなかった場合には存在しません<Route>。に使用<Route path="..." component={YourComponent}/>する必要this.props.historyがありYourComponentます。
vogdb

508

React-Router v2

最新のリリース(v2.0.0-rc5)では、推奨されるナビゲーション方法は、履歴シングルトンを直接プッシュすることです。コンポーネントドキュメントの外部でのナビゲーションで実際に動作していることがわかります

関連抜粋:

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

新しいreact-router APIを使用している場合は、コンポーネント内のhistoryfrom を使用する必要があります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を変更するためにのみ使用できます。


15
新しいAPIは使用せず、を使用してimport { browserHistory } from './react-router'履歴を作成することを忘れないでくださいimport createBrowserHistory from 'history/lib/createBrowserHistory'。後で、あなたがアクセスすることができますhistory:コンポーネントの小道具からthis.props.history('/some/path')
リカルドPedroni

7
var browserHistory = require('react-router').browserHistory; browserHistory.goBack();
ボビー

7
react-router-redux pushはURLのみを変更し、実際にはページを変更しません。両方を行うには、browserHistoryからインポートしreact-routerて使用しますbrowserHistory.push('/my-cool-path')。残念ながら、これは簡単に見つけることはできません。github.com/reactjs/react-router/blob/master/docs/guides/...
アンドリューSamuelsen

4
this.props.history.push( '/')を使用していますが、URLのみが変更されます...実際のルーティングはここでは行われません。何が欠けていますか?
rgcalsaverini 2016年


56

ここでは、あなたがこれを行う方法ですreact-router v2.0.0ES6react-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
現在の推奨事項はhistory、@ Bobbyが述べているシングルトンを使用することだと思います。使用することはできますcontext.routerが、これらのコンポーネントの単体テストを行うと、コンテキスト内でこれだけがインスタンス化されないため、これらのコンポーネントを単体テストすることが非常に困難になります。
George Mauer

2
@GeorgeMauerコードが実行されている場所に依存すると思います。反応ドキュメントによると、サーバーで実行する場合はcontext.routerの使用をお勧めします。github.com/reactjs/react-router/blob/master/upgrade-guides/...
KumarM

50

React-Router 4.x回答:

私の側では、外部コンポーネントでも実行できる単一の履歴オブジェクトが欲しいです。私がやりたいのは、オンデマンドでインポートする単一のhistory.jsファイルを用意し、それを操作することです。

BrowserRouterルーターに変更して、履歴プロップを指定するだけです。これは、必要に応じて操作できる独自の履歴オブジェクトがあること以外は何も変更しません。

が使用するライブラリである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>;
    }
}

2018年4月16日編集:

実際にレンダリングされたコンポーネントから移動する必要がある場合 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
React Routerのドキュメントを除いて、ほとんどの場合、のRouter代わりにを使用する必要はありませんBrowserRouter。オブジェクトをBrowserRouter作成して維持historyします。["Reduxなどの状態管理ツールとの高度
router

2
それは私が時間と経験を通じて学んだことです。通常はデフォルトを使用するthis.props.historyことをお勧めしますが、コンポーネントではないクラスや、Reactコンポーネントとして構築されていないその他のツールで、このようなことを行うのに役立つ解決策はまだ見つけていません小道具を渡すことができます。ご意見ありがとうございます:)
Eric Martin

44

これについては、サーバー側を制御していないため、ハッシュルーター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((
  <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()
  }
})

1
ありがとう。多分私は何かが欠けています。これは、上位2つの回答とまったく同じではありませんか?
George Mauer

2
「ハッシュ」ナビゲーションを使用している場合は、「react-router」v2に追加のモジュール「history」をインストールする必要があります(奇妙なハッシュクエリを回避したい場合)。browserHistoryを使用する代わりに、useRouterHistory(createHashHistory)( {queryKey:false})。これが私がこれを投稿した主な理由です。ハッシュ履歴でナビゲートする方法を示しました。
Alexey Volodko 2016年

1
ああ、なるほど、あなたは正しいです。私はもうそのプロジェクトには参加していませんがhistory、どちらのアプローチを使用することをお
勧めし

4
なぜこの答えが最善ではないのですか?なぜContextやHOCやイベントのプロトタイプを使ってトラブルを起こすのですか?履歴をインポートして、好きな場所で使用しないのはなぜですか?トレードオフを理解しようとしています
storm_buster 2017年

@storm_busterトレードオフはありません。ES6モジュールがあり、それらを使用する必要があります!これは、ツール(この場合は反応)をすべてに使用する典型的なショーケースです。実際には使用したくないものも含みます。
Capaj 2018

40

React Router V4

tl:dr;

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 +プロパティ初期化子を使用して状態を初期しています。興味があればこちらご覧ください。


これが私が見つけた最良の答えです。withRouterリロードされているルートにすでにいるときは使用できませんでした。私たちのケースでは、すでにルート上にある場合、または他の場所から選択的に実行する必要がありますsetState(原因return <Redirect>history.push()
カルマカゼ

とても、とても賢い。しかも非常にシンプルです。Tks。行全体のクリックを処理したかったので、ReactRouterTable内で使用しました。状態を設定するためにonRowClickで使用されます。setState({navigateTo: "/ path /" + row.uuid});
Lovato 2018年

これは弾丸証明の答えです。
Nitin Jadhav

31

警告:この回答は1.0より前のReactRouterバージョンのみを対象としています

私はこの回答を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を参照してください


26

何かがうまくいく前に、私はこれを少なくとも10通りの方法で試しました!

@Felipe SkinnerのwithRouter答えは私にとって少し圧倒的でした、そして、私が新しい "ExportedWithRouter"クラス名を作りたいと思っていませんでした。

これは、現在のReact-Router 3.0.0とES6で最も簡単でクリーンな方法です。

ES6を搭載したReact-Router 3.xx:

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

1
それは完全にうまくいきます。しかし200 OK30xコードの代わりに応答します。この問題を解決するにはどうすればよいですか?
Muhammad Ateeq Azam

1
わからない。これは外部リクエストではないため、私には思い付きませんでした。ページの内容を変更するために、ページの独自のコードを使用するブラウザです。必要に応じて、手動のJavaScriptリダイレクトをいつでも実行できます。
Ben Wheeler

1
@withRouterと一緒にクラスデコレータとして使用することもできます... mobxに最適
Dan

21

プログラムでナビゲーションを行うには、新しい履歴をの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;

react-routerのバージョンを書いてください
Ash

19

ES6 + Reactコンポーネントの場合、次のソリューションがうまくいきました。

私はFelippeスキナーをフォローしましたが、私のような初心者を助けるためにエンドツーエンドのソリューションを追加しました。

以下は私が使用したバージョンです:

「react-router」:「^ 2.7.0」

"反応する": "^ 15.3.1"

以下は、react-routerを使用したプログラムによるナビゲーションを使用した私のreactコンポーネントです。

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

19

最善の方法とは言えないかもしれませんが... react-router v4を使用すると、次のTypescriptはいくつかのアイデアを与える可能性があります。

以下のレンダリングされたコンポーネントでは、たとえばLoginPagerouterオブジェクトはアクセス可能であり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')
);


1
withRouterとbrowserHistoryを使用しないのはなぜですか?
Erwin Mayer

1
@Erwin APIはv4では異なります。こちらのgithub.com/ReactTraining/react-router/issues/3847をご覧ください。
mcku 2016年

1
@mcku react-router v4のtypescript dtsファイルはどこで入手しましたか?
jmathew 16

1
@jmathew react-router v4の型定義がありません
mcku

16

リアクト・ルータV4ES6

あなたは使用することができるwithRouterthis.props.history.push

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

class Home extends Component {

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

export default withRouter(Home);

2
すでに他のいくつかの回答で言及されています(上部の回答の詳細を含む)
George Mauer

13

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

11


ホセ・アントニオ・ポスティゴとベン・ウィーラーからの以前の答えに基づいてい
ますか?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がインストールされていても。"react-router": "^ 3.0.0"および
"@ types / react-router": "^ 2.0.41"


11

地平線上の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は、react-routerの使用/更新方法を示すサンプルアプリであり、アプリをナビゲートするサンプル機能テストが含まれています


5
これは、レンダー機能からのナビゲートに最適ですが、ライフサイクルフックやreduxなどからナビゲートする方法を知りたいのですが?
ルーベンマルティネスジュニア

11

反応ルータv4で。この2つの方法に従って、プログラムでルーティングします。

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

二番

履歴スタックの現在のエントリを置き換えます

小道具の履歴を取得するには、コンポーネントをラップする必要がある場合があります

withRouter


ありがとう!! ベストアンサー
Taha Farooqui

9

ハッシュまたはブラウザの履歴を使用している場合は、次のことができます

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

2
hashHistory.push、未定義のプロパティ「プッシュ」を読み取ることができません。これらはどこからインポートしますか?
ArchNoob 2017

「react-router」から{hashHistory}をインポートします。この方法で上部にインポートできます。
Zaman Afzal 2017

私はredux sagaファイルのコードサンプルを使用しています。あなたが言った方法でインポートして使用していますが、TypeErrorが発生し続けます。
ArchNoob 2017

8

現在のReactバージョン(15.3)this.props.history.push('/location');では問題なく動作しましたが、次の警告が表示されました。

browser.js:49警告:[react-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;

1
これはV4で機能します。まあ...閉じる...実際にはthis.context.router.history.push( '/ back-location');である必要があります。
velohomme 2017

7

React-Router V4

バージョン4を使用している場合は、私のライブラリ(恥知らずなプラグイン)を使用して、アクションをディスパッチするだけですべてが機能します。

dispatch(navigateTo("/aboutUs"));

トリプラー


5

これをreact-router v4に実装する際に問題に直面している人。

以下は、rexアクションから反応アプリをナビゲートするための実用的なソリューションです。

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の問題のコメント


4

react-router-reduxを使用してRR4 w / 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を使用してコンポーネントを反応させるフックの方が良い場合があります。


1
react-router-redux長い間非推奨/アーカイブされています
オリゴフレン

4

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


1
よろしくお願いします。react-routerとreactのどのバージョンを参照しているか注意してください。これは、常に利用できるとは限らなかった新しい変更です
George Mauer

3

正解は執筆時の私にとってのものでした

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

ただし、コンポーネントにPropTypeを追加する必要があります

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

PropTypesをインポートすることを忘れないでください

import PropTypes from 'prop-types';

react-routerのバージョンと、react-routerからインポートしたものを書き留めてください
Ash

インポートするものは何もありません。これはバージョン「react-router」です: "^ 4.2.0"
Webmaster

3

多分最善の解決策ではないかもしれませんが、それは仕事を成し遂げます:

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

基本的に、1つのアクション(この場合はポストの削除)に関連付けられたロジックは、リダイレクトのトリガーを呼び出すことになります。DOMノード「トリガー」をマークアップに追加して、必要なときに便利に呼び出せるようにするため、これは理想的ではありません。また、Reactコンポーネントでは望ましくない可能性があるDOMを直接操作します。

それでも、このタイプのリダイレクトはそれほど頻繁には必要ありません。したがって、コンポーネントマークアップに1つまたは2つの追加の非表示リンクがあっても、特に意味のある名前を付ければ、それほど害はありません。


なぜこれを受け入れられたソリューションで使用するのか説明できますか?
George Mauer

これは、議論された問題に対する代替ソリューションにすぎません。すでに述べたように、理想的ではありませんが、プログラムによるリダイレクトでは問題なく機能します。
neatsu

2

これは私にとってはうまくいきました、特別なインポートは必要ありません:

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

もちろん、これには特別なインポートが必要です。コンポーネントが単独でhistory追加されたわけではありませんprops。これは、使用するためにインポートする必要があるHoCに由来します(によって直接送信されるコンポーネントはRoute、そのHoCによって自動的にラップされますが、インポートが必要ですRoute...)
George Mauer

2

代わりにhookrouterを使用してください。react-routerの最新の代替手段です。

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

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

選択ボックスを介したリンクに関するOPの質問に答えるには、次のようにします。

navigate('/about');

ご参考までに。著者自身がこのライブラリを「概念実証」と呼んでおり、ほぼ1年間(2019年6月)活動がありませんでした。
MEMark

@MEMarkそれはすでに完璧だからです
StefanBob

さて、38の未解決の問題は、バージョン2.0がオーサーによると完全な書き直しになるという事実とともに、そうではないと述べています。
MEMark

1

React Router v4 +の場合

<Redirect>コンポーネントを使用できる)最初のレンダリング自体の間に移動する必要がないと想定すると、これがアプリで行っていることです。

nullを返す空のルートを定義します。これにより、履歴オブジェクトにアクセスできます。あなたはあなたのトップレベルでこれを行う必要があります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>
  );
}

1

react-router-dom:5.1.2

  • このサイトには3つのページがあり、そのすべてがブラウザーで動的にレンダリングされます。

  • ページが更新されることはありませんが、サイト内を移動するときに、React RouterがURLを最新に保つ方法に注意してください。これにより、ブラウザの履歴が保持され、戻るボタンやブックマークなどが適切に機能するようになります

  • スイッチは、そのすべての子要素を検索し、そのパス現在のURLと一致する最初の1をレンダリングします。複数のルートがあるときにいつでも使用できますが、一度にレンダリングするのはそのうちの1つだけです。

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";



export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

        <hr />

        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

// You can think of these components as "pages"
// in your app.

function Home() {
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}

function About() {
  return (
    <div>
      <h2>About</h2>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
    </div>
  );
}```

SOへようこそ!答えが多い質問に答えるときは、自分の利点を示すようにしてください。
DavidGarcíaBodego

これは、マークアップではなく、命令的なjsからプログラムでそれを行う方法であるという質問にも答えません。
George Mauer

1

したがって、私の答えでは、プログラムでルートにリダイレクトする3つの異なる方法があります。一部のソリューションはすでに提示されていますが、次のソリューションは、追加のデモアプリケーションを備えた機能コンポーネントにのみ焦点を当てています。

次のバージョンを使用します。

反応:16.13.1

反応-dom16.13.1

react-router:5.2.0

react-router-dom:5.2.0

typescript:3.7.2

構成:

したがって、最初のソリューションはを使用してHashRouterおり、次のように構成されています。

<HashRouter>
    // ... buttons for redirect

    <Switch>
      <Route exact path="/(|home)" children={Home} />
      <Route exact path="/usehistory" children={UseHistoryResult} />
      <Route exact path="/withrouter" children={WithRouterResult} />
      <Route exact path="/redirectpush" children={RedirectPushResult} />
      <Route children={Home} />
    </Switch>
</HashRouter>

についてのドキュメントから<HashRouter>

A <Router>URL(すなわちのハッシュ部分を使用してwindow.location.hashURLと同期して、あなたのUIを維持します)。

ソリューション:

  1. を使用<Redirect>してプッシュするuseState

リダイレクトの処理にRedirectPushAction使用できる機能コンポーネント(私のリポジトリのコンポーネント)で使用useStateします。トリッキーな部分は、リダイレクトが発生したら、redirect状態をに戻す必要があることですfalse。遅延して使用setTimeOutすることで0、Reactがコミットするまで待機していますRedirect DOMにするし、次に使用するためにボタンを取得します。

以下の私の例を見つけてください:

const [redirect, setRedirect] = useState(false);
const handleRedirect = useCallback(() => {
    let render = null;
    if (redirect) {
        render = <Redirect to="/redirectpush" push={true} />

        // in order wait until commiting to the DOM
        // and get back the button for clicking next time
        setTimeout(() => setRedirect(false), 0);
    }
    return render;
}, [redirect]);

return <>
    {handleRedirect()}
    <button onClick={() => setRedirect(true)}>
        Redirect push
    </button>
</>

<Redirect>ドキュメントから:

をレンダリングする<Redirect>と、新しい場所に移動します。新しい場所は、サーバー側のリダイレクト(HTTP 3xx)と同様に、履歴スタックの現在の場所をオーバーライドします。

  1. useHistoryフックを使用:

私のソリューションにはUseHistoryAction、以下を表すと呼ばれるコンポーネントがあります:

let history = useHistory();

return <button onClick={() => { history.push('/usehistory') }}>
    useHistory redirect
</button>

useHistoryフックは私たちに私たちのプログラムで移動したり、変更ルートを助け履歴オブジェクトへのアクセスを提供します。

  1. を使用withRouterして、historyから取得しpropsます。

と呼ばれる1つのコンポーネントを作成しWithRouterAction、以下のように表示します。

const WithRouterAction = (props:any) => {
    const { history } = props;

    return <button onClick={() => { history.push('/withrouter') }}>
        withRouter redirect
    </button>
}

export default withRouter(WithRouterAction);

withRouterドキュメントから読む:

高次コンポーネントを介して、historyオブジェクトのプロパティと最も近い<Route>の一致にアクセスできwithRouterます。withRouter更新渡しますmatchlocationと、historyそれがレンダリングするたび包まコンポーネントに小道具。

デモ:

より適切に表現するために、これらの例を使用してGitHubリポジトリを構築しました。以下で見つけてください。

https://github.com/norbitrial/react-router-programmatically-redirect-examples

これが役に立てば幸いです!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.