繁体   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