简体   繁体   English

ComponentDidUpdate SetState ReactJS 无限循环

[英]ComponentDidUpdate SetState ReactJS Infinite loop

Even though there are many questions with the same subject line, I could not get an answer for my problem.即使有很多问题的主题行相同,我也无法得到我的问题的答案。

Problem问题

I have a select dropdown.我有一个选择下拉菜单。 On click of which, I call an Api which fetches some key values.点击它,我调用一个 Api 来获取一些关键值。 I consider this set of key value input fields as a component.我将这组键值输入字段视为一个组件。 So each and every time onChange of my select drop-down, I have used lifecycle methods to handle API Calls.所以每次我选择下拉菜单的 onChange 时,我都使用生命周期方法来处理 API 调用。 Also, I record these input key values and send back their state to parent component.此外,我记录这些输入键值并将它们的状态发送回父组件。

According to ReactJS lifecycle methods:根据 ReactJS 生命周期方法:

I use我用

componentDidMount To call the API for the first time after initial render. componentDidMount初始渲染后第一次调用API。 This works.这有效。

componentDidUpdate To call the API for subsequent API calls on select drop-down change. componentDidUpdate在选择下拉更改时为后续 API 调用调用 API。 But here is the problem.但问题就在这里。 When I try to update the state of input fields the program falls into an infinite loop and hence there are infinite API calls.当我尝试更新输入字段的状态时,程序陷入无限循环,因此有无限的 API 调用。 I am pretty sure after debugging that the problem is with setState(), But I couldnt find the best way to handle states in componentDidUpdate method.调试后我很确定问题出在 setState() 上,但我找不到在 componentDidUpdate 方法中处理状态的最佳方法。

This link exactly replicates my problem but i want a standardized solution链接完全复制了我的问题,但我想要一个标准化的解决方案

Hope this is clear.希望这很清楚。 Thanks for the help in advance!提前感谢您的帮助!

This is spelled out pretty clearly in the docs :这在文档中非常清楚地说明:

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you'll cause an infinite loop.可以在 componentDidUpdate () 中立即调用 setState()但请注意,它必须包含在上面示例中的条件中,否则会导致无限循环。

You can use setState() within componentDidUpdate() .您可以在componentDidUpdate()使用setState() componentDidUpdate() But you have to use the condition for that.但是您必须为此使用条件。 Otherwise, it get infinite loop.否则,它会无限循环。

As the example,作为例子,

 componentDidUpdate(){
    if(this.props.id !== this.state.id) {
        this.setState({
            id: this.props.id 
        });
    }
 }

This happens because setState triggers a call to componentDidUpdate.发生这种情况是因为 setState 触发了对 componentDidUpdate 的调用。

When componentDidUpdate is called, setState does not check whether or not state change has occurred.调用 componentDidUpdate 时,setState 不会检查是否发生了状态更改。 It simply calls componentDidUpdate again and again, which leads to stackoverflow.它只是一次又一次地调用 componentDidUpdate,这会导致 stackoverflow。

  class Component extends React.Component{
    constructor(props){
      super(props);
      this.state = {changeState: false}
    }
    componentDidMount(){
      this.setState({changeState: true});
    }
    componentDidUpdate(){
        this.setState({changeState: false});
    } 
 }

Here, first changeState is set to false in constructor, and then componentDidMount is triggered, which sets state of changeState to true.这里首先在构造函数中将changeState设置为false,然后触发componentDidMount,将changeState的状态设置为true。 This state change triggers componentDidUpdate, which sets the state of changeState again to true.此状态更改触发 componentDidUpdate,它再次将 changeState 的状态设置为 true。 This triggers componentDidUpdate again and again.这会一次又一次地触发 componentDidUpdate。

You have to check the real difference between two state objects.您必须检查两个状态对象之间的真正区别。 Below you can find my solution, My state object has movies, which is an array of objects.你可以在下面找到我的解决方案,我的状态对象有电影,它是一个对象数组。 I edited and movie and then comparing these two arrays.我编辑和电影,然后比较这两个数组。

    async componentDidUpdate(prevProps, prevState) {

        if (prevState.movies.filter (e => this.state.movies.includes(e))) {
        const response = await axios.get("http://localhost:3002/movies");
        this.setState({ movies: response.data })
    }
}

是的,您不能在 componentDidUpdate 内设置状态(),它会导致无限循环。相反,您可以调用函数 onChange 事件并更改那里的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM