web-dev-qa-db-ja.com

this.props.history.Pushは一部のコンポーネントで機能し、他のコンポーネントでは機能しません

browserHistory.Pushを使用してプログラムでページを変更しようとしています。私のコンポーネントの1つにありますが、その中に埋め込まれたコンポーネントにはありません。

誰かが私のコンポーネントが親コンポーネントではなく子コンポーネントに対してのみ以下のエラーをスローする理由を知っていますか?

未定義のプロパティ「プッシュ」を読み取ることができません

親コンポーネント

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

class ParentView extends Component {

constructor(props) {
    super(props);
    this.addEvent = this.addEvent.bind(this);
  }

changePage() {
    this.props.history.Push("/someNewPage");
  }

render() {
    return (
      <div>
        <div>
          <button onClick={this.changePage}>Go to a New Page!</button>
        </div>

        <ChildView />  // this is the child component where this.props.history.Push doesn't work 

      </div>
    );
  }
}

function mapStateToProps(state) {
    return {
        user: state.user
    };
}

function matchDispatchToProps(dispatch) {
    return bindActionCreators({
      setName: setName
    }, dispatch)
}

export default connect(mapStateToProps, matchDispatchToProps)(ParentView);

子コンポーネント

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

    class ChildView extends Component {

    constructor(props) {
        super(props);
        this.addEvent = this.addEvent.bind(this);
      }

    changePage() {
        this.props.history.Push("/someNewPage");
      }

    render() {
        return (
          <div>
            <div>
              <button onClick={this.changePage}>Go to a New Page!</button>
            </div>

          </div>
        );
      }
    }

    function mapStateToProps(state) {
        return {
            user: state.user
        };
    }

    function matchDispatchToProps(dispatch) {
        return bindActionCreators({
          setName: setName
        }, dispatch)
    }

    export default connect(mapStateToProps, matchDispatchToProps)(ChildView);

ルーター

// Libraries
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { browserHistory } from 'react-router';

// Components
import NotFound from './components/NotFound';
import ParentView from './components/ParentView';
import ChildView from './components/ChildView';
import SomeNewPage from './components/SomeNewPage';

// Redux
import { Provider } from 'react-redux';
import {createStore} from 'redux';
import allReducers from './reducers';

const store = createStore(
  allReducers,
  window.devToolsExtension && window.devToolsExtension()
);

const routes = (
    <Router history={browserHistory}>
      <div>
        <Provider store={store}>
            <Switch>
              <Route path="/" exact component={Home} />
              <Route path="/parentView" component={ParentView} />
              <Route path="/someNewPage" component={SomeNewPage} />
              <Route path="/childView" component={ChildView} />
              <Route component={NotFound} />
            </Switch>
        </Provider>
      </div>
    </Router>
);

export default routes;

ご覧のとおり、コンポーネントは、子コンポーネントが親コンポーネントの内部にあることを除いて、実質的にまったく同じです。

注:これらのアプローチを試しましたが、問題は解決しません。

22
Rbar

質問で質問に答えました。

ご覧のとおり、コンポーネントは、子コンポーネントが親コンポーネントの内部にあることを除いて、実質的にまったく同じです。

コンポーネントがさらにネストされているという事実はあなたの問題です。 React routerはルーティング先をルーティング先のコンポーネントにのみ注入し、inでネストされたコンポーネントには注入しません。

this の質問に対する受け入れられた回答を参照してください。基本的な考え方は、ルーティングプロップを子コンポーネントに注入する方法を見つける必要があるということです。これを行うには、子をHOC withRouterでラップします。

export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView));

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

28
Chaim Friedman

WithRouterの使用は問題ありませんが、代わりのオプションは、親から子へ(withRouterを使用せずに)履歴を渡すことです。例えば:

<SignupForm history={this.props.history}/>

this.props.history.Push('/dashboard');
17
Notorious

これは、ネストされたコンポーネントの問題です。

this.props.history.Pushは、ネストされたコンポーネントでは機能しません。

したがって、解決策はwithRouterを使用することです。

withRouterを使用するには、以下の2行の下に貼り付けます。

import { withRouter } from "react-router";
export default withRouter(connect(mapStateToProps, {
    ...
})(App));
1