react-routerを使用して別のルートにリダイレクトするにはどうすればよいですか?


94

別のビューにリダイレクトするためにreact-router(バージョン^ 1.0.3)を使用して簡単にしようとしていますが、ただ疲れてきました。

import React from 'react';
import {Router, Route, Link, RouteHandler} from 'react-router';


class HomeSection extends React.Component {

  static contextTypes = {
    router: PropTypes.func.isRequired
  };

  constructor(props, context) {
    super(props, context);
  }

  handleClick = () => {
    console.log('HERE!', this.contextTypes);
    // this.context.location.transitionTo('login');
  };

  render() {
    return (
      <Grid>
        <Row className="text-center">          
          <Col md={12} xs={12}>
            <div className="input-group">
              <span className="input-group-btn">
                <button onClick={this.handleClick} type="button">
                </button>
              </span>
            </div>
          </Col>
        </Row>
      </Grid>
    );
  }
};

HomeSection.contextTypes = {
  location() {
    React.PropTypes.func.isRequired
  }
}

export default HomeSection;

必要なのは、使用を「/ login」に送信することだけです。

私に何ができる ?

コンソールのエラー:

キャッチされていないReferenceError:PropTypesが定義されていません

私のルートをファイル

// LIBRARY
/*eslint-disable no-unused-vars*/
import React from 'react';
/*eslint-enable no-unused-vars*/
import {Route, IndexRoute} from 'react-router';

// COMPONENT
import Application from './components/App/App';
import Contact from './components/ContactSection/Contact';
import HomeSection from './components/HomeSection/HomeSection';
import NotFoundSection from './components/NotFoundSection/NotFoundSection';
import TodoSection from './components/TodoSection/TodoSection';
import LoginForm from './components/LoginForm/LoginForm';
import SignupForm from './components/SignupForm/SignupForm';

export default (
    <Route component={Application} path='/'>
      <IndexRoute component={HomeSection} />
      <Route component={HomeSection} path='home' />
      <Route component={TodoSection} path='todo' />
      <Route component={Contact} path='contact' />
      <Route component={LoginForm} path='login' />
      <Route component={SignupForm} path='signup' />
      <Route component={NotFoundSection} path='*' />
    </Route>
);

こんにちは!routes定義を投稿できますLinkか?また、コンポーネントを使用していない理由がある場合はどうしますか?また、どのようなエラーが発生するかを説明します。
aarosil 2016年

ボタンの代わりに<Link to="/login">Log In</Link>
aarosil

また、使用している反応ルーターのバージョンは何ですか?手続き的にリダイレクトするためのコードがメジャーバージョン間で変更されました。
mjhm

4
の場合、Uncaught ReferenceErrorとして呼び出しますがPropTypes、それをインポートしない場合は、PropTypeをそのままインポートするか使用する必要がありますReact.PropTypes
aarosil

1
@JoshDavidMiller良い点しかし、react-router5分以内にapiの変更には驚かないでしょう。笑冗談ですが、部分的にだけです
aarosil

回答:


33

簡単な答えとして、の代わりにLinkからのコンポーネントを使用できます。JSでルートを変更する方法はいくつかありますが、ここでは必要ないようです。react-routerbutton

<span className="input-group-btn">
  <Link to="/login" />Click to login</Link>
</span>

1.0.xでプログラム的に行うには、clickHandler関数内で次のようにします。

this.history.pushState(null, 'login');

ここのアップグレードドキュメントから取得

あなたが持っているべきです this.historyによってルートハンドラコンポーネントに配置ますreact-routerroutes定義で言及されているものの下にある子コンポーネントの場合、それをさらに渡す必要がある


2
これはクールなソリューションですが、私がそれを使用しない理由は、最初に一種の検証のように行う必要があるため、これを次のような関数に入れる必要があるif (true) { // redirect to login}ためです。機能
反応さ

5
JSXでも同じことができます{validation && <Link to="/login" />Click to login</Link>}。検証がfalseの場合、何もレンダリングされません。
aarosil

私はあなたが何を意味するかを知っていますが、検証が真であればリダイレクトがなければボタンがそこにある必要があります。そうでなければ、エラーメッセージが表示されます。
反応

@TheUnnamed私はJSでそれを行う方法を示すために回答を更新しました
aarosil

1
> Uncaught TypeError:undefinedのプロパティ 'pushState'を読み取れません
反応

91

1)反応ルーター> V5 useHistoryフック:

あなたが持っている場合React >= 16.8、機能のコンポーネントを使用できuseHistory 反応し、ルータからフックを

import React from 'react';
import { useHistory } from 'react-router-dom';

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

    const handleClick = () => {
        history.push("/path/to/push");
    }

    return (
        <div>
            <button onClick={handleClick} type="button" />
        </div>
    );
}

export default YourComponent;

2)反応ルーター> V4 withRouterHOC:

@ambarがコメントで述べたように、React-routerはV4以降にコードベースを変更しています。ここにドキュメントがあります- 公式withRouter

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

class YourComponent extends Component {
    handleClick = () => {
        this.props.history.push("path/to/push");
    }

    render() {
        return (
            <div>
                <button onClick={this.handleClick} type="button">
            </div>
        );
    };
}

export default withRouter(YourComponent);

3)React-router <V4 browserHistory

この機能は、react-routerを使用して実現できますBrowserHistory。以下のコード:

import React, { Component } from 'react';
import { browserHistory } from 'react-router';

export default class YourComponent extends Component {
    handleClick = () => {
        browserHistory.push('/login');
    };

    render() {
        return (
            <div>
                <button onClick={this.handleClick} type="button">
            </div>
        );
    };
}

4)Redux connected-react-router

あなたが再来してあなたのコンポーネントを接続している、と設定している場合は接続-反応ルータあなたがしなければならないすべてである this.props.history.push("/new/url");つまり、あなたが必要としないwithRouter注入するHOCをhistoryコンポーネント小道具に。

// reducers.js
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';

export default (history) => combineReducers({
    router: connectRouter(history),
    ... // rest of your reducers
});


// configureStore.js
import { createBrowserHistory } from 'history';
import { applyMiddleware, compose, createStore } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import createRootReducer from './reducers';
...
export const history = createBrowserHistory();

export default function configureStore(preloadedState) {
    const store = createStore(
        createRootReducer(history), // root reducer with router state
        preloadedState,
        compose(
            applyMiddleware(
                routerMiddleware(history), // for dispatching history actions
                // ... other middlewares ...
            ),
        ),
    );

    return store;
}


// set up other redux requirements like for eg. in index.js
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router';
import { ConnectedRouter } from 'connected-react-router';
import configureStore, { history } from './configureStore';
...
const store = configureStore(/* provide initial state if any */)

ReactDOM.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <> { /* your usual react-router v4/v5 routing */ }
                <Switch>
                    <Route exact path="/yourPath" component={YourComponent} />
                </Switch>
            </>
        </ConnectedRouter>
    </Provider>,
    document.getElementById('root')
);


// YourComponent.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
...

class YourComponent extends Component {
    handleClick = () => {
        this.props.history.push("path/to/push");
    }

    render() {
        return (
          <div>
            <button onClick={this.handleClick} type="button">
          </div>
        );
      }
    };

}

export default connect(mapStateToProps = {}, mapDispatchToProps = {})(YourComponent);

3
「browserHistory」は、react-routerの一部ではなくなったようです。
ambar 2017

BrowserRouterにはプッシュ機能がありません
johnnyodonnell

@ambar @johnnyodonnell react-router-domが行う
toinetoine

23

react-routerを使用して別のルートにリダイレクトするにはどうすればよいですか?

たとえば、ユーザーがリンクをクリックすると、<Link to="/" />Click to route</Link>react-routerが検索し、ユーザーを/使用Redirect toして、ログインルートのような別の場所にユーザーを送信できます。

以下からのドキュメントのためのReactRouterTraining

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

import { Route, Redirect } from 'react-router'

<Route exact path="/" render={() => (
  loggedIn ? (
    <Redirect to="/dashboard"/>
  ) : (
    <PublicHomePage/>
  )
)}/>

to:文字列、リダイレクト先のURL。

<Redirect to="/somewhere/else"/>

to:オブジェクト、リダイレクト先の場所。

<Redirect to={{
  pathname: '/login',
  search: '?utm=your+face',
  state: { referrer: currentLocation }
}}/>

提供されたソリューションはエラーをスローします<Redirect> elements are for router configuration only and should not be rendered
t1gor 2018年

9

Webのための最も簡単なソリューション!

2020年までに、以下との
連携が確認されています。

"react-router-dom": "^5.1.2"
"react": "^16.10.2"

useHistory()フックを使用してください!

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


export function HomeSection() {
  const history = useHistory();
  const goLogin = () => history.push('login');

  return (
    <Grid>
      <Row className="text-center">          
        <Col md={12} xs={12}>
          <div className="input-group">
            <span className="input-group-btn">
              <button onClick={goLogin} type="button" />
            </span>
          </div>
        </Col>
      </Row>
    </Grid>
  );
}

すばらしい、それを行うためのフック方法を探していました!IDEに「シンボルを解決できません...」という警告が表示されていても、機能します!
Rafael Moni

7

react-router v2.8.1(おそらく他の2.xxバージョンも同様ですが、テストしていません)では、この実装を使用してルーターリダイレクトを実行できます。

import { Router } from 'react-router';

export default class Foo extends Component {

  static get contextTypes() {
    return {
      router: React.PropTypes.object.isRequired,
    };
  }

  handleClick() {
    this.context.router.push('/some-path');
  }
}

時々:this.context.router.history.push( '/ some-path');
象嘉道2017

4

最も簡単な解決策は次のとおりです。

import { Redirect } from 'react-router';

<Redirect to='/componentURL' />

しかし、エラーが発生します:不変が失敗しました:<ルーター>の外で<リダイレクト>を使用しないでください
Prateek Gupta

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