React 组件中的错误导致应用程序重新渲染,从而导致无限循环。为啥?

Posted

技术标签:

【中文标题】React 组件中的错误导致应用程序重新渲染,从而导致无限循环。为啥?【英文标题】:Error in React component causing app to re-render, which is causing infinite loop. Why?React 组件中的错误导致应用程序重新渲染,从而导致无限循环。为什么? 【发布时间】:2018-03-08 03:44:03 【问题描述】:

还没有包含代码,我想知道是否有人遇到过您遇到的问题:

有一个包含在connect 中的组件,在我的情况下为apollo-client 让子组件也包裹在connect 中,在componentWillMount 中进行调度 在子组件中引发错误 获得无限循环

我所处的情况是,任何抛出错误的子组件都会导致父组件再次运行render,而所有子组件似乎都运行componentWillMount,但不运行componentWillUnmount

错误不会被记录,并且直到调用堆栈溢出时才会出现在控制台中。

这会导致它们都重新连接到 Redux、调度操作以及再次抛出错误,因为它们再次挂载,从而导致循环。

我可以尝试重现,但这需要相当长的时间,只是想知道是否有人遇到了类似的问题,可以提供一些地方查看。

【问题讨论】:

没有使用过 Apollo,也不能说我认识到了这个问题。但出于调试目的,我可能会在再次调度操作之前尝试在componentWillMount 内部进行一些检查,看看我是否可以打破循环并希望错误不会以这种方式丢失。或者在componentWillMount 中使用断点,以便您可以随时停止它。并使用 Redux devtools 之类的工具来查看已调度的操作以及它们是否包含预期的有效负载等。github.com/zalmoxisus/redux-devtools-extension 【参考方案1】:

您不应在 componentWillMount 中调度任何操作。任何被认为是可变的都应该在 componentDidMount 中完成。 componentWillMount 类似于构造函数。该组件尚未安装。组件不知道任何状态(除非您指定),但该状态在组件实际安装之前不会实现,这发生在 componentDidMount 中。理想情况下,您应该坚持使用构造函数,而不是真正使用 componentWillMount。对于任何 API 调用或调度,您应该将它们保存在 cDM 中

【讨论】:

没有看到任何代码,我不能给你最好的答案。我上面所说的仍然是正确的,但这可能只能解决您的部分问题。此外,作为参考,React 实际上也记录了这一点。尝试使用 componentDidMount 交叉引用它,在该页面的下方找到了一点。 reactjs.org/docs/react-component.html#componentwillmount【参考方案2】:

克莱顿是对的; ComponentWillMount 在某种程度上是一种反模式,尽管它曾经是道路和真理。您可能想使用ComponentDidMount

但是,既然你提到了 throwing,那么 React 16 有一个 componentDidCatch lifecycle hook 就毫无价值了。这使您可以捕获错误并在反应中处理它:

错误边界是 React 组件,可在其子组件树中的任何位置捕获 javascript 错误,记录这些错误并显示回退 UI

理论上,这应该允许您处理错误和短路connect

【讨论】:

以上是关于React 组件中的错误导致应用程序重新渲染,从而导致无限循环。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

更改数组中的一个状态会导致在 React Hooks 中重新渲染整个循环生成的自定义组件

即使状态没有改变,为啥 setState 会导致太多的重新渲染错误

从组件中的 useState 多次调用 state updater 会导致多次重新渲染

React/Redux 存储更新但组件未重新渲染

React生命周期, setState、props改变触发的钩子函数

在 React 中提升状态不会导致不必要的重新渲染吗?