web-dev-qa-db-ja.com

React-router v4 this.props.history.Push(...)が機能しない

this.props.history.Push(..)を使用してプログラムでルーティングしようとしていますが、うまくいかないようです。

ルーターは次のとおりです。

import {
 BrowserRouter as Router,
 Route
} from 'react-router-dom';

<Router>
 <Route path="/customers/" exact component={CustomersList} />
 <Route path="/customers/:id" exact component="{Customer} />
</Router>

CustomerListでは、顧客のリストが表示されます。顧客(li)をクリックすると、アプリケーションが顧客にルーティングされます。

import { withRouter } from 'react-router'

class Customers extends Component {
  static propTypes = {
    history: PropTypes.object.isRequired
  }

 handleCustomerClick(customer) {
   this.props.history.Push(`/customers/${customer.id}`);
 }

 render() {
   return(
    <ul>
      { this.props.customers.map((c) =>
        <li onClick={() => this.handleCustomerClick(c)} key={c.id}>
          {c.name}
        </li> 
    </ul>
  )

 }
}

//connect to redux to get customers

CustomersList = withRouter(CustomersList);
export default CustomersList;

コードは部分的ですが、状況を完全に示しています。ブラウザーのアドレスバーはhistory.Push(..)に応じて変化しますが、ビューは更新されず、Customerコンポーネントはレンダリングされず、CustomersListはまだ存在しています。何か案は?

23
Andrea Ongaro

だから私は答えを期待してこの質問に来ましたが、役に立ちませんでした。利用した

const { history } = this.props;
history.Push("/thePath")

同じプロジェクトで、期待どおりに機能しました。さらに実験を重ねて比較対照すると、このコードがネストされたコンポーネント内で呼び出されると実行されないことに気付きました。そのため、レンダリングされたページコンポーネントのみがこの関数を呼び出して、適切に機能します。

ワーキングサンドボックスの検索 こちら

  • 履歴:v4.7.2
  • 反応:v16.0.0
  • 反応ドーム:v16.0.0
  • react-router-dom:v4.2.2
12

リアクションルーターの最新バージョンでは、状況が少し変わっているようです。これで、コンテキストを介して履歴にアクセスできます。 this.context.history.Push('/path')

このgithubの問題への返信も参照してください。 https://github.com/ReactTraining/react-router/issues/4059

11
cgat

子コンポーネントに履歴をロードしようとすることができます。そのためには、小道具に「歴史」を渡します。そんな感じ:

  return (
  <div>
    <Login history={this.props.history} />
    <br/>
    <Register/>
  </div>
)
5
Taha A.

私(react-router v4、react v16)の問題は、ナビゲーションコンポーネントが大丈夫だったことです:

import { Link, withRouter } from 'react-router-dom'

class MainMenu extends Component {

  render() {
    return (
            ...
            <NavLink to="/contact">Contact</NavLink>
            ...
    );
  }
}

export default withRouter(MainMenu);

どちらかを使用して

to="/contact" 

または

OnClick={() => this.props.history.Push('/contact')}; 

動作は同じままでした-ブラウザのURLは変更されましたが、間違ったコンポーネントがレンダリングされ、同じ古いURLでルーターが呼び出されました。

原因はルーター定義にあります。 MainMenuコンポーネントをRouterコンポーネントの子として移動する必要がありました!

// wrong placement of the component that calls the router
<MainMenu history={this.props.history} />
<Router>
   <div>
     // this is the right place for the component!
     <MainMenu history={this.props.history} />
     <Route path="/" exact component={MainPage} />
     <Route path="/contact/" component={MainPage} />
   </div>
</Router>
2
Jan Matousek

古い質問のようですが、それでも関連性があります。

blocked update の問題だと思います。

主な問題は、現在のURL(現在のURL)と同じコンポーネント(Costumers)によって新しいURL(ルート)がレンダリングされることになっていることです。

そのため、解決策はかなり単純で、ウィンドウのURLを小道具として作成します。したがって、reactは小道具の変更(したがってURLの変更)を検出し、それに応じて動作する可能性があります。

推奨:完全に制御されていないキー付きコンポーネント と呼ばれる公式の反応ブログで説明されているニースのユースケース。

解決策は、render() { return( <ul>から変更することです

render() { return( <ul key={this.props.location.pathname}>

そのため、react-routerによって場所が変更されるたびに、コンポーネントは(reactによって)破棄され、新しいコンポーネントは正しい値(reactによって)で開始されます。

ああ、locationをpropとしてコンポーネント(Costumers)に渡します。まだ渡されていない場合、リダイレクトが発生します。

それが誰かを助けることを願っています。

2
arcol

CustomersListではなくCustomersコンポーネントをエクスポートする必要があります。

    CustomersList = withRouter(Customers);
    export default CustomersList;
0

ルーターでは使用しないでください。

handleSubmit(e){
   e.preventDefault();
   this.props.form.validateFieldsAndScroll((err,values)=>{
      if(!err){
        this.setState({
            visible:false
        });
        this.props.form.resetFields();
        console.log(values.username);
        const path = '/list/';
        this.props.history.Push(path);
      }
   })
}

うまくいきます。

0
YangFang