簡體   English   中英

setState 循環遍歷一組道具 - React ComponentDidUpdate

[英]setState while looping through an array of props - React ComponentDidUpdate

我正在做一個項目,需要在 componentDidMount 之后設置狀態。(期望子組件中的道具是在掛載時派生的。因此我只能在之后設置狀態)我能想出的唯一選項是使用 componentDidUpdate。

props 父組件是一個從 axios 獲取的數據派生的數組。

這里的目標是遍歷數組並從下面代碼中顯示的 URL 中獲取每個數組的數據,然后設置子組件的 setState。

嘗試我通常做的事情,我無法停止在 componentDidUpdate 處觸發的無限循環。

這是我的代碼。

家長

  render(){

  return (
    <div className="App">

      <EachCountry countryList= {this.state.CountriesList}/>

    </div>

子組件

     async componentDidUpdate(prevProps, prevState, snapshot){
    if(this.state.countryList.length < this.props.countryList.length){
        await this.props.countryList.map(m=>{
                axios ({
                    method:"get",
                    url:`/countryupdate/${m}`
                }).then(res=>{
                    console.log(res.data)
                    this.setState(crntState=>({
                        countryList:[...crntState.countryList, res.data]
                    }))  
                })
        })
        }    
    }

控制台日志工作得很好。 但是當我嘗試 setState 時,我遇到了像 5000 條錯誤消息這樣的無限循環。

我的另一個技巧是

 async componentDidUpdate(prevProps, prevState, snapshot){
    if(this.state.countryList.length < this.props.countryList.length){
        await this.props.countryList.map(m=>{
                var newdata =  axios ({
                    method:"get",
                    url:`/countryupdate/${m}`
                })
                console.log(newdata)
                    this.setState(crntState=>({
                        countryList:[...crntState.countryList, newdata.data]
                    }))  
        })
        }    
    }

而這個返回的是承諾而不是所需的數據。

幫助家庭

我錯過了什么?

Your issue is likely caused by derived state: state that is dependent on props and is an anti pattern in react: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state .html#when-to-use-derived-state

請參閱下面的可行解決方法,但建議您重組數據流。

嘗試這樣的事情,首先只向 state 發送 1 個更新:

async componentDidMount(){

  //variable to store new data
  const allNewData = [];
  
  //an async data fetcher
  const getNewData = async(m) => {
    let newData = await axios({
      method: "get",
      url: `/countryupdate/${m}`
    })
    allNewData.push(newData.data);
  }
  
  //an async for loop
  async function updateData() {
    for (const m of countryList) {
      await getNewData(m);
    }
    this.setState(crntState => ({
      countryList: [...crntState.countryList, ...allNewData]
    }))
  }

  await updateData();
}

如果上述方法不起作用(可能不起作用),則使用 getDerivedStateFromProps 而不是 componentDidMount 並將 setState 替換為 return obj

static getDerivedStateFromProps(props, state) {
  if (this.state.countryList.length < this.props.countryList.length) {
      ...
      return {
        countryList: [...state.countryList, ...allNewData]
      };
     }

     let newState = await updateData();
     return newState; 
}

如果這不起作用,則恢復到 componentDidMount 並使用 shouldComponentUpdate 作為條件

shouldComponentUpdate(nextProps, nextState) {
    return this.state.countryList.length != nextState.countryList.length; 
}

如果我沒有得到正確的語法,請查看此代碼片段

 function mockAxios(m) { return new Promise(function(resolve, reject) { setTimeout(() => resolve({ data: `${m}'s data` }), 1000) }); } function setState(arr) { console.log(arr); console.log("state has been set") } const countryList = ["A", "B", "C", "D", "E"]; /////////////////////////////////////////////// async function componentDidMount() { const allNewData = []; async function getNewData(m) { let newData = await mockAxios(m); allNewData.push(newData.data); } async function updateData() { for (const m of countryList) { await getNewData(m); console.log("fetching data...") } setState(allNewData); } await updateData(); } componentDidMount();

暫無
暫無

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

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