为啥 addChangeListener 应该在 componentDidMount 而不是 componentWillMount 中?

Posted

技术标签:

【中文标题】为啥 addChangeListener 应该在 componentDidMount 而不是 componentWillMount 中?【英文标题】:Why should addChangeListener be in componentDidMount instead of componentWillMount?为什么 addChangeListener 应该在 componentDidMount 而不是 componentWillMount 中? 【发布时间】:2015-09-03 02:25:20 【问题描述】:

我看到这条线是对这里另一个问题的回答:

“componentWillMount 应该是 componentDidMount,否则你会泄漏节点中的事件发射器。”

我真的不明白。谁能详细解释一下?

更多信息:

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

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

此外,在初始渲染和注册监听器之间没有危险期,其中 Store 可以在不触发渲染的情况下更改,导致视图与 Store 不同步(原始问题中给出的示例问题)。如果侦听器在componentDidMount 中注册,您要么需要确保在子代的componentDidMount 调用中未更改Store,否则在注册侦听器后强制重新渲染/重新同步,如果在@ 中完成987654333@ 以相反的文档顺序完成,这可能是多项式复杂度(取决于 React setStates 的聚合方式/是否聚合)。

【讨论】:

componentWillMount 已弃用,您能否更新此答案?我很想知道在哪里注册监听器以及在哪里取消注册监听器 @xaphod 我已经有一段时间没有处理这个问题了,但这里是official documentation 处理这个关于弃用更改的问题。我没有对此进行详细审查,但数据更新竞赛仍然是一个问题,因为他们建议在订阅componentDidMount 后明确更新状态。我不知道新的异步行为有什么安全的替代方案。【参考方案2】:

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

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

另一方面,componentDidMount 在组件附加到 DOM(真实的)后被调用。

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

我建议你阅读这些链接:

https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount https://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount https://facebook.github.io/react/tips/use-react-with-other-libraries.html

【讨论】:

问题是,如果我修改componentDidMount 中的DOM,当他注意到DOM 与Virtual 不同时,它会给我错误! 这类事情通常有解决办法。我将 React 与 Ace 富文本编辑器、jQuery Resizable、jQuery sortable 和许多其他“在 React 的世界之外”工作的东西一起使用,并且没有任何问题。您必须注意不要更改 React 呈现的内容,但在大多数情况下您可以添加新元素。如果没有关于您的任务的更多信息,很难提供帮助。

以上是关于为啥 addChangeListener 应该在 componentDidMount 而不是 componentWillMount 中?的主要内容,如果未能解决你的问题,请参考以下文章

为啥有人应该在 git commit 之前使用 git add?或者为啥有人应该使用 git add 呢?

在执行语义分割任务时我应该减去图像均值吗?为啥或者为啥不?

你应该同步运行方法吗?为啥或者为啥不?

为啥我们不应该在 javascript 中使用 ++? [复制]

为啥/何时应该使用静态声明变量?

为啥我们应该在颤振中使用选项?