ComponentDidUpdate设置状态ReactJS无限循环

4
即使有很多相同主题的问题,我仍然无法得到我的问题的答案。
问题:
我有一个选择下拉框。 点击后,我调用一个API来获取一些关键值。 我将这组键值输入字段视为组件。 因此,每次更改我的选择下拉菜单时,我都使用生命周期方法来处理API调用。 此外,我记录这些输入关键值并将其状态发送回父组件。
根据ReactJS生命周期方法:
我使用
componentDidMount 在初始渲染后第一次调用API。 这个可以工作。
componentDidUpdate 对于随后的API调用,选择下拉框发生更改。 但是问题在于:当我尝试更新输入字段的状态时,程序会陷入无限循环,因此会有无限的API调用。 经过调试,我非常确定问题出在setState()上,但我找不到在componentDidUpdate方法中处理状态的最佳方法。
这个链接完全复制了我的问题,但我想要一个标准化的解决方案。
希望这个清楚明了。 非常感谢您的帮助!
5个回答

7
这在文档中已经很清楚地阐述了:
componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

在componentDidUpdate()中,您可以立即调用setState(),但请注意必须像上面的示例中那样将其包装在条件语句中,否则会导致无限循环。

你好@Madbreaks,我有一个计时器,在状态中定义了一个计数器,当componentDidMount时,我使用setInterval来减少计时器,在componentDidUpdate中,我想要改变屏幕上文本的颜色,但是我得到了相同的错误componentDidUpdate() { if (this.state.timer === 0) { clearInterval(this.interval); this.setState({ resendColor: '#257bd1', // disable: false, }); } } - Oliver D

2
你可以在 componentDidUpdate() 中使用 setState()。但是你必须使用条件语句,否则会导致无限循环。

例如:

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

0

是的,你不能在componentDidUpdate中使用setState(),否则会导致无限循环。相反,你可以在onChange事件中调用一个函数并在那里改变状态。


谢谢!我理解了这个解决方法。但是 ReactJS 的文档建议我们可以在 componentDidUpdate 中设置状态。想知道我误解了哪个概念。请查看这篇博客,您能告诉我哪里出了错吗? - bks4line
1
当你在componentDidUpdate中调用setState()时,它会调用以下生命周期方法:shouldComponentUpdate-->componentWillUpdate--->render---再次--->componentDidUpdate。这样会创建无限循环。 - Debabrata Mohanta
1
这是错误的。您可以componentDidUpdate中调用setState,请参见我的答案。 - Madbreaks

0
这是因为setState会触发对componentDidUpdate的调用。
当调用componentDidUpdate时,setState不检查是否发生了状态改变。它只是一遍又一遍地调用componentDidUpdate,从而导致堆栈溢出。
  class Component extends React.Component{
    constructor(props){
      super(props);
      this.state = {changeState: false}
    }
    componentDidMount(){
      this.setState({changeState: true});
    }
    componentDidUpdate(){
        this.setState({changeState: false});
    } 
 }

这里,首先在构造函数中将 changeState 设置为 false,然后触发 componentDidMount,将 changeState 的状态设置为 true。这个状态变化会触发 componentDidUpdate,再次将 changeState 的状态设置为 true。这会一遍又一遍地触发 componentDidUpdate。


0

你需要检查两个状态对象之间的真正差异。下面是我的解决方案,我的状态对象有电影,它是一个对象数组。我编辑了一部电影,然后比较这两个数组。

    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 })
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接