Skip to content

fix(RN): enhance RN IntersectionObserver lifecycle and cleanup logic - #2585

Open
wangshunnn wants to merge 6 commits into
masterfrom
codex/fix-rn-intersection-observer-cleanup
Open

fix(RN): enhance RN IntersectionObserver lifecycle and cleanup logic#2585
wangshunnn wants to merge 6 commits into
masterfrom
codex/fix-rn-intersection-observer-cleanup

Conversation

@wangshunnn

@wangshunnn wangshunnn commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Fix (RN)

背景

排查 RN 曝光监听连续报错时,发现业务在滚动回调中反复创建 IntersectionObserver,未及时断开旧实例,导致实例累积并触发 Hermes 属性存储上限。

排查同时发现框架在主动断开和组件卸载时存在清理不完整的问题。本 PR 修复框架侧生命周期清理;业务侧反复创建 observer 的问题已同步业务方另行调整跟进。

修复内容

  • 修正组件卸载时 observer 列表的读取位置,批量清理时避免边遍历边删除造成漏项。
  • disconnect() 完整移除注册及持有的引用,取消尚未执行的节流测量任务,忽略在途测量结果,确保断开后不再触发业务回调,并支持重复调用。
  • 调整注册顺序,避免页面注册失败后仍在组件列表中保留实例。

验证

  • 新增单测通过,Hermes 连续创建并断开 22 万次后,页面注册表和组件列表均为空。

微信原生表现观察

本次真机环境:iOS 26.7、微信 8.0.76、基础库 3.17.2。

场景 真机结果
正常对照 A、B、C 在初始、移出、移入阶段均正常回调
A 的回调中断开 B、C 不再回调,后续位置变化也没有回调
断开后原实例再次 observe() 抛错,不能恢复观察
断开后原实例再次 relativeTo() 在设置参照阶段就抛错,后面的 observe() 未执行

if (this._disconnected || relativeRect === IgnoreTarget) return
observeRects.forEach((observeRect, index) => {
if (observeRect === IgnoreTarget) return
if (this._disconnected || observeRect === IgnoreTarget) return

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同步的地方没必要再加这个判断

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是考虑业务可能在前一个节点的回调里调用 disconnect(),然后我先按断开后停止后续节点回调来处理了。我也一起验证下微信的表现。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

微信真机上验证首个回调中断开后,其余节点不再回调,这里可以保留。

this.component._intersectionObservers = this.component._intersectionObservers || []
this.component._intersectionObservers.push(this)

this._disconnected = false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要测试微信的表现,disconnect之后是否还能重新建立观察对象

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

微信原生真机表现:先 observe() 再 disconnect() 后,原实例再次 observe() 会抛错;重新调用 relativeTo() 也会抛错,无法恢复观察。

this.observerRefs = null
this.relativeRef = null
this.callback = noop
this.previousIntersectionRatio = []

@hiyuki hiyuki Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些小的属性重置没有必要啊,只需要执行 remove(this.component._intersectionObservers, this) 把根引用断掉自然就能被gc,保险起见在保留个this.component = null就可以,当然前提是微信当中的执行过disconnect后当前的intersectionObserver就再也不可用

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已优化,真机验证了这个前提成立

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants