React-router:手動でリンクを呼び出す方法は?


131

ReactJSとReact-Routerは初めてです。propsを介し<Link/>react-routerからオブジェクトを受け取るコンポーネントがあります。ユーザーがこのコンポーネント内の「次へ」ボタンをクリックするたびに、<Link/>オブジェクトを手動で呼び出します。

現在、refsを使用してバッキングインスタンスにアクセスし、<Link/>生成された「a」タグを手動でクリックしています。

質問:リンクを手動で呼び出す方法はありthis.props.next.goますか(例:)?

これは私が現在持っているコードです:

//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />

//in Document.js
...
var Document = React.createClass({
   _onClickNext: function() {
      var next = this.refs.next.getDOMNode();
      next.querySelectorAll('a').item(0).click(); //this sounds like hack to me
   },
   render: function() {
      return (
         ...
         <div ref="next">{this.props.next} <img src="rightArrow.png" onClick={this._onClickNext}/></div>
         ...
      );
   }
});
...

これは私が欲しいコードです:

//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />

//in Document.js
...
var Document = React.createClass({
   render: function() {
      return (
         ...
         <div onClick={this.props.next.go}>{this.props.next.label} <img src="rightArrow.png" /> </div>
         ...
      );
   }
});
...

回答:


198

React Router v4-リダイレクトコンポーネント(2017年4月15日更新)

v4で推奨される方法は、レンダリングメソッドがリダイレクトをキャッチできるようにすることです。状態または小道具を使用して、リダイレクトコンポーネントを表示する必要があるかどうかを判断します(これにより、リダイレクトがトリガーされます)。

import { Redirect } from 'react-router';

// ... your class implementation

handleOnClick = () => {
  // some action...
  // then redirect
  this.setState({redirect: true});
}

render() {
  if (this.state.redirect) {
    return <Redirect push to="/sample" />;
  }

  return <button onClick={this.handleOnClick} type="button">Button</button>;
}

リファレンス:https : //reacttraining.com/react-router/web/api/Redirect

React Router v4-参照ルーターコンテキスト

RouterReactコンポーネントに公開されているのコンテキストを利用することもできます。

static contextTypes = {
  router: PropTypes.shape({
    history: PropTypes.shape({
      push: PropTypes.func.isRequired,
      replace: PropTypes.func.isRequired
    }).isRequired,
    staticContext: PropTypes.object
  }).isRequired
};

handleOnClick = () => {
  this.context.router.push('/sample');
}

これが内部でどのように<Redirect />機能するかです。

リファレンス:https : //github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60

React Router v4-外部で変更された履歴オブジェクト

それでもv2の実装と同様のことを行う必要がある場合は、のコピーを作成BrowserRouterhistoryて、エクスポート可能な定数として公開できます。以下は基本的な例ですが、必要に応じて構成して、カスタマイズ可能な小道具を挿入できます。ライフサイクルには注意点がありますが、v2と同様に、常にルーターを再レンダリングする必要があります。これは、アクション関数からのAPIリクエスト後のリダイレクトに役立ちます。

// browser router file...
import createHistory from 'history/createBrowserHistory';
import { Router } from 'react-router';

export const history = createHistory();

export default class BrowserRouter extends Component {
  render() {
    return <Router history={history} children={this.props.children} />
  }
}

// your main file...
import BrowserRouter from './relative/path/to/BrowserRouter';
import { render } from 'react-dom';

render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>
);

// some file... where you don't have React instance references
import { history } from './relative/path/to/BrowserRouter';

history.push('/sample');

最新のBrowserRouter拡張: https //github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js

React Router v2

browserHistoryインスタンスに新しい状態をプッシュします。

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

リファレンス:https : //github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md


7
hashHistory.push( '/ sample'); browserHistoryの代わりにhashHistoryを使用している場合
sanath_p

1
containerElement = {<Link to = "/" />}を使用しても常にリンクが呼び出されるとは限らないため、これはmaterial-uiライブラリで特に便利です
Vishal Disawar 2017年

2
リダイレクトオプションでは、プッシュを指定する必要があることに注意してください(つまり、<Redirect push />)。デフォルトでは、手動でリンクを呼び出すのとまったく同じではない置換を行います
aw04

1
@jokabを使用でき、<NavLink />ではなく<リンク/>のgithub.com/ReactTraining/react-router/blob/master/packages/...
マット・ロー

1
リダイレクトは機能しませんが、withRouterを使用したaw04ソリューションはよりシンプルで機能します
stackdave

90

React Router 4には、 以下 を介してオブジェクトにアクセスできるwithRouter HOCがれていhistoryますthis.props

import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'

class Foo extends Component {
  constructor(props) {
    super(props)

    this.goHome = this.goHome.bind(this)
  }

  goHome() {
    this.props.history.push('/')
  }

  render() {
    <div className="foo">
      <button onClick={this.goHome} />
    </div>
  }
}

export default withRouter(Foo)

9
これは私にとってはうまくいき、最も簡単な解決策のように見えます。
Rubycut 2017年

5
これが最良の解決策です。なぜ票数が少ないのかわかりません。
Benoit

1
はい、リンクを数回クリックしてもブラウザは動作しません。実際に戻るには、ブラウザを数回クリックして戻る必要があります
Vladyslav Tereshyn

@VladyslavTereshyn条件付きロジックを追加できます:if((this.props.location.pathname + this.props.location.search)!== navigateToPath){...}
MattWeiler

15

ではバージョン5.xは、使用することができますuseHistoryのフックをreact-router-dom

// Sample extracted from https://reacttraining.com/react-router/core/api/Hooks/usehistory
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>
  );
}

これが最良の解決策です。:あなたは、いくつかの条件ロジックを追加した場合、ユーザーが同じボタンを複数回クリックしたとき、あなたは歴史の中で重複したエントリを避けることができますif ((routerHistory.location.pathname + routerHistory.location.search) !== navigateToPath) { routerHistory.push(navigateToPath); }
MattWeiler

history変数を宣言する必要があり、ディレクトリの呼び出しuseHistory().pushはフックルールでは許可されていません
onmyway133

これは最も現代的な反応のある解決策のようです。
ヨンジェ

8

https://github.com/rackt/react-router/blob/bf89168acb30b6dc9b0244360bcbac5081cf6b38/examples/transitions/app.js#L50

または、これをクリックして実行することもできます(より暴力的な解決策):

window.location.assign("/sample");

コードの行が変わるので、詳細をコピーしてここで答えを説明すると、答えが良くなります。また、assignプロパティではなく、関数です。
WiredPrairie 2015年

(しかし、あなたはまだファイルの特定の行へのリンクを持っています)。リンクではなく、具体的な提案を回答に含めてください。
WiredPrairie 2015年

回答ありがとう@grechut。しかし、私はドキュメントがルーターについてまったく何も知らないことを確認したいと思います。私が期待している動作は、「ユーザーが右矢印をクリックした場合、次の関数を呼び出す」です。次の関数はリンクかそうでないかもしれません。
Alan Souza 2015年

React(FBおよびGoogleリダイレクトを使用したログイン画面)の外部で処理されるページがいくつかあるため、「browserHistory.push( '/ home');」以降、これらのページのナビゲーションでこれを必要としました。URLを変更しただけで、ページをルーティングできませんでした。ありがとうございました。
デボラ2017年

7
これは、@ grechutページをリロードしますが、react routerを使用するアプリケーションにとって望ましい動作ではありません。
Abhas 2017

2

さて、私はそのための適切な解決策を見つけることができたと思います。

今、送信する代わりに <Link/>よう小道具ドキュメント、Iセンドへ<NextLink/>反応し、ルータリンク用のカスタムラッパーです。そうすることで、Documentオブジェクト内にルーティングコードを配置することを避けながら、Link構造の一部として右矢印を使用できます。

更新されたコードは次のようになります。

//in NextLink.js
var React = require('react');
var Right = require('./Right');

var NextLink = React.createClass({
    propTypes: {
        link: React.PropTypes.node.isRequired
    },

    contextTypes: {
        transitionTo: React.PropTypes.func.isRequired
    },

    _onClickRight: function() {
        this.context.transitionTo(this.props.link.props.to);
    },

    render: function() {
        return (
            <div>
                {this.props.link}
                <Right onClick={this._onClickRight} />
            </div>  
        );
    }
});

module.exports = NextLink;

...
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
var nextLink = <NextLink link={sampleLink} />
<Document next={nextLink} />

//in Document.js
...
var Document = React.createClass({
   render: function() {
      return (
         ...
         <div>{this.props.next}</div>
         ...
      );
   }
});
...

PS:最新バージョンのreact-routerを使用している場合は、のthis.context.router.transitionTo代わりに使用する必要がありますthis.context.transitionTo。このコードは、react-routerバージョン0.12.Xで正常に動作します。


2

React Router 4

v4では、コンテキストを介してpushメソッドを簡単に呼び出すことができます。

this.context.router.push(this.props.exitPath);

コンテキストは次のとおりです。

static contextTypes = {
    router: React.PropTypes.object,
};

を使用するBrowserRouterと、コンポーネントのコンテキストオブジェクトにオブジェクトが含まれませんrouter。私は何か悪いことをしていますか?
ピラウ

コンポーネント(上記の2番目のブロック)でコンテキストを設定していますか?
Chris

よろしくお願いします!最終的にこれは私のために働きました: router: React.PropTypes.object.isRequiredisRequired鍵なしでは機能しなかった理由がわかりません。また、コンテキスト<Link>を取得できたようhistoryですが、複製できませんでした。
pilau

興味深いもの-コードペンをお持ちの場合、それでも行き詰まっている場合はデバッグをお手伝いします
Chris

this.props.history.push()React Router v4で使用できるようです。私は、React Routerが渡す小道具を調べただけでこれを見つけました。それは動作するようですが、それが良いアイデアかどうかはわかりません。
sean_j_roberts 2017年

-1

再びこれはJSです:)これはまだ動作します...

var linkToClick = document.getElementById('something');
linkToClick.click();

<Link id="something" to={/somewhaere}> the link </Link>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.