簡體   English   中英

React 子組件在父 State 更改后不更新

[英]React Child Component Not Updating After Parent State Change

我正在嘗試制作一個不錯的 ApiWrapper 組件來填充各種子組件中的數據。 從我讀過的所有內容來看,這應該有效: https://jsfiddle.net/vinniejames/m1mesp6z/1/

class ApiWrapper extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      response: {
        "title": 'nothing fetched yet'
      }
    };
  }

  componentDidMount() {
    this._makeApiCall(this.props.endpoint);
  }

  _makeApiCall(endpoint) {
    fetch(endpoint).then(function(response) {
      this.setState({
        response: response
      });
    }.bind(this))
  }

  render() {
    return <Child data = {
      this.state.response
    }
    />;
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: props.data
    };
  }

  render() {
    console.log(this.state.data, 'new data');
    return ( < span > {
      this.state.data.title
    } < /span>);
  };
}

var element = < ApiWrapper endpoint = "https://jsonplaceholder.typicode.com/posts/1" / > ;

ReactDOM.render(
  element,
  document.getElementById('container')
);

但出於某種原因,當父 state 更改時,子組件似乎沒有更新。

我在這里錯過了什么嗎?

您的代碼有兩個問題。

您的子組件的初始狀態是從 props 設置的。

this.state = {
  data: props.data
};

引用此SO 答案

將初始狀態作為prop傳遞給組件是一種反模式,因為getInitialState (在我們的例子中是構造函數)方法僅在組件第一次渲染時被調用。 再也不會了。 這意味着,如果您重新渲染該組件並將不同的值作為prop傳遞,則該組件將不會做出相應的反應,因為該組件將保持第一次渲染時的狀態。 它非常容易出錯。

因此,如果您無法避免這種情況,理想的解決方案是使用方法componentWillReceiveProps來偵聽新的道具。

將以下代碼添加到您的子組件將解決您的子組件重新渲染問題。

componentWillReceiveProps(nextProps) {
  this.setState({ data: nextProps.data });  
}

第二個問題是fetch

_makeApiCall(endpoint) {
  fetch(endpoint)
    .then((response) => response.json())   // ----> you missed this part
    .then((response) => this.setState({ response }));
}

這是一個工作小提琴: https : //jsfiddle.net/o8b04mLy/

如果上述解決方案仍未解決您的問題,我建議您查看一下如何更改狀態,如果您沒有返回新對象,那么有時 react 會發現新的前一個狀態和更改后的狀態沒有區別,這是在更改狀態時始終傳遞新對象的好習慣,看到新對象的反應肯定會重新渲染所有需要訪問該更改狀態的組件。

例如: -

在這里,我將更改我狀態中一組對象的一個​​屬性,看看我如何將所有數據分散到一個新對象中。 另外,下面的代碼對你來說可能有點陌生,它是一個 redux reducer 函數,但別擔心它只是一種改變狀態的方法。

export const addItemToCart = (cartItems,cartItemToBeAdded) => {
        return cartItems.map(item => {
            if(item.id===existingItem.id){
                ++item.quantity;        
            }
            // I can simply return item but instead I spread the item and return a new object
            return {...item} 
        })
    } 

只需確保您正在使用新對象更改狀態,即使您對狀態進行了微小的更改,也只是將其分散到一個新對象中然后返回,這將在所有適當的位置觸發渲染。 希望這有幫助。 如果我在某個地方錯了,請告訴我:)

有些事情你需要改變。

fetch得到響應時,它不是一個 json。 我一直在尋找如何獲得這個 json 並且我發現了這個鏈接

另一方面,您需要考慮constructor函數只調用一次。

因此,您需要更改在<Child>組件中檢索數據的方式。

在這里,我留下了一個示例代碼: https : //jsfiddle.net/emq1ztqj/

我希望這有幫助。

接受的答案和componentWillReceiveProps

已接受答案中的componentWillReceiveProps調用已棄用,並將從 React 版本 17 React 文檔中刪除: UNSAFE_componentWillReceiveProps()

在 React 中使用派生的 state 邏輯

正如 React 文檔所指出的那樣,使用派生的 state(意思是:組件反映其 props 中發生的變化)會使您的組件更難思考,並且可能是一種反模式。 React 文檔:你可能不需要 Derived State

當前解決方案: getDerivedStateFromProps

如果您選擇使用派生的 state,當前的解決方案是使用getDerivedStateFromProps調用,如@DiogoSanto 所說。

getDerivedStateFromProps 在調用 render 方法之前被調用,在初始掛載和后續更新時都是如此。 它應該返回 object 以更新 state,或返回 null 以更新任何內容。 反應文檔: static getDerivedStateFromProps()

如何使用componentWillReceiveProps

此方法無法訪問實例屬性。 它所做的一切都描述了 React 如何從給定的 props 計算新的 state。 每當 props 發生變化時,React 都會調用此方法並將此方法返回的 object 作為新的 state。

class Child extends React.Component {
    constructor() {
        super(props);
        // nothing changed, assign the state for the 
        // first time to teach its initial shape. 
        // (it will work without this, but will throw 
        // a warning)
        this.state = {
            data: props.data
        };
    }

    componentWillReceiveProps(props) {
        // return the new state as object, do not call .setState()
        return { 
            data: props.data
        };
    }

    render() {
        // nothing changed, will be called after 
        // componentWillReceiveProps returned the new state, 
        // each time props are updated.
        return ( 
            <span>{this.state.data.title}</span>
        );
    }
}

警告

  • 根據父組件中發生的更改重新渲染組件可能會讓用戶感到厭煩,因為會丟失該組件上的用戶輸入。
  • 派生 state 邏輯會使組件更難理解,繼續思考。 明智地使用。

暫無
暫無

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

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