react-router跳转时useOnScreen调用unobserve报参数非Element错误如何解决
报错根本原因
React组件卸载流程中,DOM元素会先被移除、ref.current被置为null,之后才会执行useEffect的清理函数,所以原代码直接取ref.current调用unobserve就会触发类型错误。
关于你现有写法的顾虑
你现在加非空判断的写法完全不会造成资源浪费:
- 组件卸载后,这个IntersectionObserver实例没有被任何其他代码引用,会被JS垃圾回收机制自动清理
- 就算没有调用
unobserve,Observer没有观察目标时也不会执行任何回调,不会占用额外CPU资源
更严谨的优化方案
如果你想要更彻底的资源释放,避免任何潜在的边界问题,可以修改useOnScreen钩子的useEffect逻辑,在闭包内缓存当前观察的DOM元素,同时主动调用disconnect释放Observer资源:
// useOnScreen 钩子内部优化后的useEffect写法 useEffect(() => { // 提前缓存当前的DOM元素,避免后续ref.current变动影响 const targetElement = ref.current; if (!targetElement) return; const observer = new IntersectionObserver( ([entry]) => setIsIntersecting(entry.isIntersecting), { rootMargin: rootMargin } ); observer.observe(targetElement); return () => { // 直接用闭包缓存的元素,不需要判断是否为null observer.unobserve(targetElement); // 主动断开Observer所有监听,彻底释放资源 observer.disconnect(); }; }, [ref, rootMargin])
该方案的优势:
- 完全避免了
ref.current为null的问题,不需要额外的非空判断 - 主动调用
disconnect可以立即释放Observer的所有资源,比等待垃圾回收更高效 - 就算后续ref指向发生变化,也只会清理之前观察的对应元素,不会出现误操作
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

