为什么 addChangeListener 应该在 componentDidMount 而不是 componentWillMount?

Why should addChangeListener be in componentDidMount instead of componentWillMount?

我将此行视为对此处另一个问题的回答:

"componentWillMount should be componentDidMount, or else you'll leak event emitters in node."

我也不是很懂。有人可以更详细地解释一下吗?

更多信息:

使用 flux 构建一个 React 应用程序,作为初始渲染的一部分,子组件计算一些数据。理想情况下,在计算完这些数据后,我想调用一个操作,用一部分新数据更新商店的状态。

通常,更新商店的状态会发出导致重新呈现的更改事件。但是,因为直到 componentDidMount(而不是在 componentWillMount 中)才添加更改侦听器,所以我的顶级组件无法侦听初始渲染期间发生的更改并启动重新渲染。

如果我将 addChangeListener 移动到 componentWillMount 似乎可以解决这个问题,但上面的引述表明这是个坏主意?

如果没有更多上下文,很难理解这句话的意思。我可以告诉你的是,这两种方法之间存在巨大差异。

一方面,componentWillMount 在组件实际添加到 DOM 之前被调用。这是您必须在浏览器呈现组件之前更新组件状态并呈现它的最后机会。

另一方面,一旦组件附加到 DOM(真实的),就会调用 componentDidMount

您真正需要的取决于您的用例。一般情况下,componentDidMount用于与其他库集成(如jQuery),它提供了一种修改组件渲染的HTML的方法。

我建议您阅读这些链接:

我认为应该在 componentDidMount 中设置侦听器的流行观点是错误的,因为它可以防止同构应用程序中出现问题。我认为在 98% 的非同构应用程序的情况下,在 componentWillMountcomponentDidMount 中设置侦听器将以相同的方式工作,但它在概念上是错误的,并且在 2% 的情况下(例如示例在原始问题中给出)它会做错事。

React 源代码中有 git 个问题讨论和评论,建议最好根本不在服务器上调用 componentWillMount,但如果不是,则在将服务器预渲染与客户端初始渲染进行比较的校验和测试中会产生问题。在服务器上具有 componentWillMount 意味着在这种情况下它不会作为组件生命周期的一部分执行,但这是在任何情况下都被用作不将其视为生命周期一部分的借口。

事实上,如果您不创建同构应用程序,componentWillMount 正是注册侦听器的正确位置。如果您正在创建同构应用程序,那么您必须做出一些妥协,因为 checksum/lifecycle 问题在这种情况下并不理想(也许只是测试服务器环境,然后不注册侦听器?)。

在非同构应用程序中,在 componentWillMount 中添加侦听器在某些情况下可以节省不必要的重新渲染,并将按文档顺序注册它们。文档顺序的优点是,如果您有办法在重新呈现组件时刷新未决事件(例如,MutationObserver 上的 takeRecords),那么您可以确保重新呈现文档向下而不是自下而上,将渲染复杂度从多项式转换为线性。

此外,在初始渲染和注册监听器之间没有危险期,Store 可以在不触发渲染的情况下更改,从而导致视图与 Store 不同步(示例中给出的问题原始问题)。如果侦听器在 componentDidMount 中注册,您需要确保商店在 componentDidMount 调用中未更改,或者在注册侦听器后强制 re-render/re-sync,如果完成in componentDidMount 以反向文档顺序完成,这可能是多项式复杂度(取决于 how/if React setStates 聚合)。