React 16.3.0+Next.js应用"Unexpected Fiber popped"警告成因咨询
嘿,这个警告我在React 16.x早期版本碰见过好几次,尤其是16.3刚推出新Ref API那会儿。结合你说的修改了ref相关代码才出现的情况,基本跑不开这几个核心原因:
新旧Ref API混用操作冲突
React 16.3刚引入createRef()和forwardRef(),如果你的代码里同时用了旧的字符串式Ref(比如<div ref="myDiv">)和新的createRef实例,而且在生命周期或事件里直接操作这些Ref引用,很容易搞乱React内部的Fiber节点管理。毕竟字符串Ref是React自己维护的,createRef是你自己持有的引用,两者的更新逻辑完全不一样,Fiber树校验时就会触发这个"Unexpected Fiber popped"警告。Render阶段直接修改Ref的current属性
要是你在组件的render()方法里直接给ref.current赋值(比如myRef.current = someDomElement),这绝对是踩坑了。Render阶段要求是纯函数式的,不能有副作用,直接修改Ref会让Fiber节点的预期状态和实际状态对不上,React在后续协调流程里就会抛出这个警告。SSR与客户端Hydration的Ref不匹配
你用了Next.js,肯定涉及服务端渲染(SSR)。如果服务端渲染的组件里用了Ref,而客户端Hydration时Ref的初始化逻辑和服务端不一致——比如服务端没生成对应的DOM节点,但客户端一上来就想访问Ref,或者Hydration时组件结构变了,Ref绑定的节点找不到了,就会导致Fiber树校验失败,触发警告。自定义Hook/第三方库的Ref传递错误
如果你改的代码涉及自定义Hook或者第三方UI库的Ref传递,比如在forwardRef里没正确把Ref往下传,或者自定义Hook返回的Ref引用被意外修改了,都会导致Fiber节点的引用链断裂,自然就会弹出这个警告。
另外提一句,React 16.3.0本身是Fiber架构刚落地没多久的版本,这个警告属于当时的Fiber树校验逻辑,后续版本修复了不少这类场景,但你的版本比较老,所以更容易触发。
给你几个排查方向:
- 先检查有没有混用字符串Ref和
createRef,尽量统一用新的Ref API; - 确保所有Ref的操作都放在
componentDidMount、componentDidUpdate或者useEffect(如果用Hook的话)里,别在Render阶段碰ref.current; - 排查SSR场景下的Ref使用,保证服务端和客户端的组件结构一致,别在服务端渲染的组件里做依赖DOM的Ref操作;
- 如果用了
forwardRef,仔细检查Ref是不是正确传递到了目标组件上。
内容的提问来源于stack exchange,提问作者Jess Telford

