簡體   English   中英

React-router v4 this.props.history.push(...) 不工作

[英]React-router v4 this.props.history.push(...) not working

我正在嘗試使用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 仍然存在。 有任何想法嗎?

所以我來到這個問題希望得到答案,但無濟於事。 我用過了

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

在同一個項目中,它按預期工作。 經過進一步的實驗和一些比較和對比,我意識到如果在嵌套組件中調用此代碼將無法運行 因此只有渲染的頁面組件才能調用此函數使其正常工作。

在此處查找工作沙盒

  • 歷史:v4.7.2
  • 反應:v16.0.0
  • 反應域:v16.0.0
  • react-router-dom: v4.2.2

在最新版本的反應路由器中,事情似乎發生了一些變化。 您現在可以通過上下文訪問歷史記錄。 this.context.history.push('/path')

另請參閱對此 github 問題的回復: https : //github.com/ReactTraining/react-router/issues/4059

您可以嘗試加載具有歷史記錄的子組件。 為此,請通過道具傳遞“歷史”。 類似的東西:

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

對我來說(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>

您可以通過withRouter高階組件訪問歷史對象的屬性和最接近的匹配項。 withRouter將在渲染時將更新的匹配、位置和歷史道具傳遞給包裝的組件。

import React, { Component } from 'react'
import { withRouter } from 'react-router'; 
// you can also import "withRouter" from 'react-router-dom';

class Example extends Component {
    render() {
        const { match, location, history } = this.props
        return (
            <div>
                <div>You are now at {location.pathname}</div>
                <button onClick={() => history.push('/')}>{'Home'}</button>
            </div>
        )
    }
}


export default withRouter(Example)

似乎是一個老問題,但仍然相關。

我認為這是一個阻止更新的問題。

主要問題是新 URL(路由)應該由與您當前所在(當前 URL)相同的組件( Costumers )呈現。

所以解決辦法很簡單,把window url作為一個prop,這樣react就有機會檢測到prop的變化(因此url變化),並采取相應的行動。

官方 React 博客中描述的一個很好的用例,名為“ 推薦:完全不受控制的組件,帶有一個鍵”

所以解決辦法是從render() { return( <ul>

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

因此,每當 react-router 更改位置時,組件就會報廢(通過反應),並且會以正確的值(通過反應)啟動一個新的組件。

哦,並將location作為 prop 傳遞給組件( Costumers ),如果尚未傳遞,則會發生重定向。

希望它可以幫助某人。

我有類似的症狀,但我的問題是我嵌套了BrowserRouter


不要嵌套BrowserRouter ,因為history對象將引用最近的BrowserRouter父對象。 因此,當您執行history.push(targeturl)並且該targeturl不在那個特定的BrowserRouter它不會匹配它的任何路由,因此它不會加載任何子組件。

解決方案

嵌套Switch而不用BrowserRouter包裝它


示例

讓我們考慮這個App.js文件

<BrowserRouter>
  <Switch>
    <Route exact path="/nestedrouter" component={NestedRouter}  />
    <Route exact path="/target" component={Target}  />
  </Switch>
</BrowserRouter>

而不是在NestedRouter.js文件中執行此操作

<BrowserRouter>
  <Switch>
    <Route exact path="/nestedrouter/" component={NestedRouter}  />
    <Route exact path="/nestedrouter/subroute" component={SubRoute}  />
  </Switch>
</BrowserRouter>

只需刪除BrowserRouterNestedRouter.js文件

  <Switch>
    <Route exact path="/nestedrouter/" component={NestedRouter}  />
    <Route exact path="/nestedrouter/subroute" component={SubRoute}  />
  </Switch>

讓我們考慮一下這種情況。 你有App.jsx作為你 ReactJS SPA 的根文件。 在其中,您的render()看起來類似於:

<Switch>
    <Route path="/comp" component={MyComponent} />
</Switch>

然后,您應該能夠在MyComponent使用this.props.history沒有問題。 假設您在MyComponent中呈現MySecondComponent ,在這種情況下,您需要以這種方式調用它:

<MySecondComponent {...props} />

這會將道具從MyComponent傳遞到MySecondComponent ,從而使this.props.historyMySecondComponent可用

您需要導出客戶組件而不是CustomerList

    CustomersList = withRouter(Customers);
    export default CustomersList;

我看到您正在使用類組件,但如果您決定切換到功能組件或在應用程序中遇到與功能組件相同的問題,您可以通過react- router使用“useHistory”鈎子 API 來解決此問題-多姆。

用法示例:

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

const Customers = ({customer}) => {
   let history = useHistory();

   const handleCustomerClick = (customer) => {
     history.push(`/customers/${customer.id}`);
   }

  return (
    //some JSX here
  );
};

你可以在這里找到官方文檔: https : //reactrouter.com/web/api/Hooks/usehistory

初學者在使用路由時犯的錯誤是直接將withRouter與組件一起使用,而不是在其間放置任何其他高階組件(或者至少是不知道將props.historyprops.history其子組件的組件)的props.history

錯誤: export default withRouter(withErrorHandler(Foo));

正確: export default withErrorHandler(withRouter(Foo));

在 react-router-dom v6 中,對歷史的支持已被棄用,但引入了導航。 如果您想在特定事件成功時將用戶重定向到特定頁面,請按照以下步驟操作:

創建一個名為 withRouter.js 的文件,並將下面給出的代碼粘貼到該文件中

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

export const withRouter = (Component) => {
  const Wrapper = (props) => {
    const navigate = useNavigate();

    return (
      <Component
        navigate={navigate}
        {...props}
        />
    );
 };

  return Wrapper;
};

現在,在您想要將用戶重定向到特定路徑/組件的任何基於類的組件中,在那里導入上面的 withRouter.js 文件並使用 this.props.navigate('/your_path_here') 函數進行重定向。

為了您的幫助,下面給出了顯示相同內容的示例代碼:

import React from 'react';
import {withRouter} from '.your_Path_To_Withrouter_Here/withRouter';

class Your_Component_Name_Here extends React.Component{
     constructor(){
       super()
       this.yourFunctionHere=this.yourFunctionHere.bind(this);
    }

    yourFunctionHere()
    {
        this.props.navigate('/your_path_here')
    }

    render()
    {
        return(
            <div>
              Your Component Code Here 
            </div>
        )
    }
}

export default withRouter(Your_Component_Name_Here);

我希望它解決了你的問題。 如果它那么贊成這個答案。 謝謝!

不要與路由器一起使用。

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

它運作良好。

您需要綁定handleCustomerClick

class Customers extends Component {
  constructor() {
    super();
    this.handleCustomerClick = this.handleCustomerClick(this)
  }
this.props.history.push(`/customers/${customer.id}`, null);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM