React中useEffect清理函数内的Ref数组为何全为null?
问题原因分析
你的代码出现这个问题有两个核心原因:
React执行顺序影响:
- 组件挂载时,
useEffect的回调会在DOM挂载完成、ref回调执行之后才触发,但你只是把localRefs指向了refs.current数组的引用,并没有保存数组元素的快照。 - 组件卸载时,React会先调用所有ref回调并传入
null(把refs.current数组的每个元素设为null),之后才执行useEffect的清理函数。此时localRefs因为和refs.current指向同一个数组,打印出来自然是包含三个null的数组。
- 组件挂载时,
引用类型的特性:
refs.current是数组(引用类型),你赋值给localRefs的是数组的引用而非元素副本。后续数组内容的修改会直接反映在localRefs上。
解决方案
要在卸载阶段获取到卸载前的DOM节点,需要在组件挂载完成后保存一份refs元素的快照,而非数组引用:
const refs = useRef([]); useEffect(() => { // 组件挂载完成后,refs.current已被ref回调赋值,此时创建元素快照 const snapshotRefs = [...refs.current]; return () => { console.log("unmounting", snapshotRefs); }; }, []); return ( <> <div ref={(el) => { refs.current[0] = el; }}></div> <div ref={(el) => { refs.current[1] = el; }}></div> <div ref={(el) => { refs.current[2] = el; }}></div> </> );
修改后,snapshotRefs是挂载完成后DOM节点的副本,卸载时即使原数组被设为null,快照也不受影响,能正确打印出卸载前的DOM元素。
内容的提问来源于stack exchange,提问作者connorhansen
相关产品推荐
相关产品推荐

