【问题标题】:Why is using setState inside componentDidUpdate seen as a bad practice in React?为什么在 React 中使用 setState 在 componentDidUpdate 中被视为不好的做法?
【发布时间】:2020-09-04 06:34:06
【问题描述】:

当道具更新时我需要更新孩子的状态,所以我做了这样的事情:

componentDidUpdate(prevProps) {
    const { searchValue, searchCriterion } = this.props;

    if (searchValue !== prevProps.searchValue) {
      this.setState({ searchValue });
    }
    if (searchCriterion !== prevProps.searchCriterion) {
      this.setState({ searchCriterion });
    }
  }

ESLint 的 airbnb 指南正在抱怨它和throwing this warning,尽管我看不到任何明显的渲染或性能问题。

警告说:

组件更新后更新状态会触发第二次 render() 调用并可能导致属性/布局抖动。

当道具具有新值时,是否有更好的方法来更新孩子的状态?

或者我应该忽略警告吗?

【问题讨论】:

  • 可以,但是如果没有保护会导致无限循环。似乎您在道具和状态中使用了相同的值。那为什么要设置状态呢?
  • 这是一个很好的观点......我真的不需要它,感谢您指出它。但是,如果有一个案例证明根据 prop 更新状态是合理的,有没有办法在不收到此警告的情况下做到这一点?
  • 标记为警告,如果您已安全检查您的守卫没有创建更新周期,则可以忽略。同意@bubulledu93 关于searchValue 属性的存储。在 props 和 state 中复制数据是一种反应反模式。您可以在需要的地方简单地从this.props 读取searchValue,并且不会延迟渲染周期。
  • 忽略我正在复制数据的事实(我现在在我的代码中使用this.props),相等性检查是否足以防止无限循环?
  • 好像itnext.io/how-to-updating-state-on-prop-changes-2296a03ef08c这样的主题有多篇文章。这取决于实际情况。钩子让useEffect更容易

标签: javascript reactjs eslint-config-airbnb


【解决方案1】:

您的代码的问题是它可能会创建一个无限循环。当您调用setState 方法时,您会触发第二个render,就像警告所说的那样,因此会触发一个新的componentDidUpdate

为了解决这个问题,您可能希望为您的状态的某些值创建一个中断条件以退出循环。例如,您可以简单地使用这样的标志:

componentDidUpdate(prevProps) {
const { searchValue, searchCriterion } = this.props;

if (this.state.isAlreadyUpdated === true) {
  this.setState({ isAlreadyUpdated: false });
  break;
} else {
  this.setState({ isAlreadyUpdated: true });
}

if (searchValue !== prevProps.searchValue) {
  this.setState({ searchValue });
}
if (searchCriterion !== prevProps.searchCriterion) {
  this.setState({ searchValue });
}

}

【讨论】:

  • 我知道你在这里做什么以及它如何防止无限循环,感谢标志上的解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
相关资源
最近更新 更多