into-piece / Step-By-Step

每天一题向前端架构师前进
4 stars 1 forks source link

关于ref #45

Open into-piece opened 3 years ago

into-piece commented 3 years ago

使用 React Hooks 声明 setInterval

function Counter() {
  let [count, setCount] = useState(0);

  useEffect(() => {
    let id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
  },[]);

  return <h1>{count}</h1>;
}

但是,这代码有一个奇怪的行为。 默认情况下,React 会在每次渲染后重执行 effects,这是有目的的,这有助于避免 React class 组件的某种 bugs。 这通常是好的,因为需要许多订阅 API 可以随时顺手移除老的监听者和加个新的。但是,setInterval 和它们不一样。当我们执行 clearInterval 和 setInterval 时,它们会进入时间队列里,如果我们频繁重渲染和重执行 effects,interval 有可能没有机会被执行! 获取不到新的值,useEffect没有依赖count

function Counter() {
  const [count, setCount] = useState(0);
  const func = useRef();

  func.current = () => {
    console.log(count);
    setCount(count + 1);
  };

  useEffect(() => {
    let id = setInterval(() => {
      func.current();
    }, 1000);
    return () => clearInterval(id);
  }, []);

  return <h1>{count}</h1>;
}

或者

setCount((pre)=>pre + 1);