React中使用Intersection Observer如何获取最新的state状态值
问题原因
这是React的闭包陷阱导致的:useEffect 仅在 infiniteLoadingRef 变化时执行一次,初始化 IntersectionObserver 时传入的 handleObserver 捕获的是首次渲染时的 someState 快照,后续组件重渲染、someState 更新后,旧的回调函数依旧引用的是初始值,所以读不到最新状态。
你之前把someState加入依赖后触发无限循环,是因为没有在useEffect的清理函数中销毁旧的观察者实例,每次state更新都会新建一个观察者,重复触发回调导致循环。
解决方案
方案1:用useRef存储最新状态(最推荐,无额外性能开销)
用ref同步最新的state值,ref是引用类型,回调中直接读取ref.current就能拿到最新值,不需要修改observer的初始化逻辑:
const [someState, setSomeState] = useState(someVal); // 新建ref同步state const someStateRef = useRef(someState); // 监听state变化更新ref useEffect(() => { someStateRef.current = someState; }, [someState]); const handleObserver = (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => { if (entries[0].isIntersecting) { // 读取ref的current属性获取最新值 console.log(someStateRef.current); } }; useEffect(() => { if (!isInfinite || !infiniteLoadingRef || !infiniteLoadingRef.current) return; const options = { root: null, rootMargin: "0px", threshold: 0, }; const observer = new IntersectionObserver(handleObserver, options); observer.observe(infiniteLoadingRef.current); // 加清理函数避免内存泄漏 return () => { observer.disconnect(); }; }, [infiniteLoadingRef]);
方案2:将state加入依赖数组,增加清理逻辑
如果需要每次state更新都重新创建观察者,可以把someState加入依赖,同时在清理函数中销毁旧的观察者,就不会出现无限循环:
useEffect(() => { if (!isInfinite || !infiniteLoadingRef || !infiniteLoadingRef.current) return; const options = { root: null, rootMargin: "0px", threshold: 0, }; const observer = new IntersectionObserver(handleObserver, options); observer.observe(infiniteLoadingRef.current); // 组件卸载/依赖变化时销毁旧观察者 return () => { observer.disconnect(); }; // 把someState加入依赖数组 }, [infiniteLoadingRef, someState]);
内容的提问来源于stack exchange,提问作者Nyi Nyi Hmue Aung
相关产品推荐
相关产品推荐

