簡體   English   中英

在 componentDidUpdate 內反應 setState 導致無限循環

[英]React setState inside componentDidUpdate causing infinite loop

有人可以幫我解決如何在componentDidUpdate而不是無限循環嗎? 一些建議說有條件語句,但我不太熟悉如何為我的代碼設置條件。

這是我的代碼的樣子:

我有一個儀表板組件,它從發生提取的外部函數獲取所有公司和項目數據,然后更新狀態。 這些項目與公司的 ID 相關聯。

我能夠獲得 JSON 中所有項目的列表,但我無法弄清楚如何在渲染后更新 componentDidUpdate 中的項目狀態。

公司儀表板.js

import { getCompanys } from "../../actions/companyActions";
import { getProjects } from "../../actions/projectActions";

class CompanyDashboard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      companies: [],
      projects: []
    };
  }

  componentWillMount() {
    // get all companies and update state
    getCompanys().then(companies => this.setState({ companies }));
  }

  componentDidUpdate(prevState) {
    this.setState({ projects: this.state.projects });
  }

  render() {
    const { companies, projects } = this.state;
    {
      companies.map(company => {
        // get all the projects
        return getProjects(company);
      });
    }
    return <div />;
  }
}

export default CompanyDashboard;

公司行動.js

import { getUser, getUserToken } from './cognitoActions';
import config from '../../config';

export function getCompanys() {
    let url = config.base_url + '/companys';
    return fetch(url, {
      method: 'GET',
      headers: {'token': getUserToken() }
    })
    .then(res => res.json())
    .then(data => { return data })
    .catch(err => console.log(err));
}

projectActions.js

import { getUserToken } from './cognitoActions';
import config from '../../config';

export function getProjects(company) {
  let url = config.base_url + `/companys/${company._id['$oid']}/projects`;
  return fetch(url, {
    method: 'GET',
    headers: {'token': getUserToken() }
  })
  .then(res => res.json())
  .then(data => { return data })
  .catch(err => console.log(err));
}

componentDidUpdate有這個簽名, componentDidUpdate(prevProps, prevState, snapshot)

這意味着每次調用該方法時,您都可以訪問您的prevState ,您可以使用它與新數據進行比較,然后根據該決定是否應該再次更新。 例如,它看起來像這樣。

componentDidUpdate(prevProps, prevState) {
  if (!prevState.length){
    this.setState({ projects: this.state.projects })
  }
}

當然這只是一個例子,因為我不知道你的要求,但這應該給你一個想法。

以下代碼沒有做任何有意義的事情。 您將 state.projects 設置為等於 state.projects。

  componentDidUpdate() {
    this.setState({ projects: this.state.projects })
  }

此外,以下代碼沒有做任何有意義的事情,因為您沒有將 company.map 的結果保存在任何地方。

    {
      companies.map((company) => {
        return getProjects(company) 
      })
    } 

很難說你認為你的代碼在做什么,但我的猜測是你認為在渲染函數中簡單地調用“companies.map(....)”會觸發 componentDidUpdate 函數。 這不是渲染的工作方式,您應該回到那個繪圖板上。 看起來您還認為在渲染函數中使用大括號 {} 將顯示大括號內的對象。 這也不是真的,您需要在組件內使用那些大括號。 例如:{項目}

如果我不得不猜測......下面的代碼是您實際想要編寫組件的方式

import { getCompanys } from '../../actions/companyActions';
import { getProjects } from '../../actions/projectActions';

class CompanyDashboard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      companies: [],
      projects: []
    }
  }

  componentWillMount() {
    getCompanys().then(companies => {
      const projectPromises = companies.map((company) => {
        return getProjects(company) 
      });

      Promise.all(projectPromises).then(projects => {
        //possibly a flatten operator on projects would go here.

        this.setState({ companies, projects });
      });


      /*
       * Alternatively, you could update the state after each project call is returned, and you wouldn't need Promise.all, sometimes redux can be weird about array mutation in the state, so look into forceUpdate if it isn't rerendering with this approach:
       * const projectPromises = companies.map((company) => {
       *   return getProjects(company).then(project => this.setState({projects: this.state.projects.concat(project)}));
       * });
       */

    )
  }

  render() {
    const { companies, projects } = this.state;

    //Not sure how you want to display companies and projects, but you would 
    // build the display components, below.
    return(
      <div>
         {projects}
      </div>
    )
  }

}

export default CompanyDashboard;

componentDidUpdate()被調用時,會傳遞兩個參數: prevPropsprevState 這與componentWillUpdate()相反。 傳遞的值是值是什么,而this.propsthis.state是當前值。

`componentDidUpdate(prevProps) {
    if (this.props.userID !== prevProps.userID) {
        this.fetchData(this.props.userID);
    }
}`

如果新的狀態/道具與以前的不同,您必須檢查狀態/道具,然后您可以允許更新您的組件。

您可以在componentDidUpdate() setState()立即調用setState()但請注意,它必須包含在上面示例中的條件中,否則會導致無限循環。 它還會導致額外的重新渲染,雖然對用戶不可見,但會影響組件性能。 如果您試圖將某些狀態“鏡像”到來自上方的道具,請考慮直接使用道具。

這是因為 componentDidUpdate 是在組件完成狀態更改后才被調用的。 因此,只有當您更改該方法中的狀態時,它才會在該方法和狀態更改過程中來回移動

暫無
暫無

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

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