React闭包陷阱的形成与解决方案

import React, { useState, useEffect, useRef, useCallback } from 'react';

function ClosureTrapDemo() {
  const [count, setCount] = useState(0);
  const latestCount = useRef(count);
  
  // 问题示例1: useState闭包陷阱
  const badIncrement = () => {
    setCount(count + 1);
    console.log('Bad increment:', count); // 旧值
  };
  
  // 解决方案1: 函数式更新
  const goodIncrement = () => {
    setCount(prev => prev + 1);
    console.log('Good increment:', count); // 仍为旧值(渲染未完成)
  };
  
  // 问题示例2: useEffect闭包陷阱
  useEffect(() => {
    const timer1 = setInterval(() => {
      console.log('Bad interval count:', count); // 总是初始值
    }, 1000);
    return () => clearInterval(timer1);
  }, []);
  
  // 解决方案2: 正确声明依赖
  useEffect(() => {
    const timer2 = setInterval(() => {
      console.log('Good interval count:', count); // 最新值
    }, 1000);
    return () => clearInterval(timer2);
  }, [count]);
  
  // 解决方案3: 使用useRef
  useEffect(() => {
    latestCount.current = count;
  });
  
  useEffect(() => {
    const timer3 = setInterval(() => {
      console.log('Ref count:', latestCount.current); // 最新值
    }, 1000);
    return () => clearInterval(timer3);
  }, []);
  
  // 解决方案4: 使用useCallback
  const showCount = useCallback(() => {
    alert(`Current count: ${count}`);
  }, [count]);
  
  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={badIncrement}>Bad Increment</button>
      <button onClick={goodIncrement}>Good Increment</button>
      <button onClick={showCount}>Show Count</button>
    </div>
  );
}

export default ClosureTrapDemo;

 

posted @ 2025-08-26 16:00  Julia-Yuan  阅读(16)  评论(0)    收藏  举报