1. 实现:页面实时刷新一般用定时器(setInterval())实现。

定时器:setInterval() - 每多少秒执行一次指定的代码。(执行多次)
延时器:setTimeout() - 多少秒以后执行指定代码。(执行1次)

定时器与延时器均为异步程序,放在异步队列里执行!

2.  注意点:

          1.  页面使用定时器一定要记得清除。

           2.  useEffect 的数组依赖不要忘记,不然只执行一次。

           3.  也可以使用useRef(为了避免setInterval变量形成闭包)

方式一: 使用数组依赖

function Index() {
  const [count, setCount] = useState(0);
 
  useEffect(() => {
    const timer = setInterval(() => {
    
    //可以调接口
    //可以存state,如setCount(count + 1)
    //可以调其他函数

    }, 1000);
    return () => clearInterval(timer);  //清除定时器不要忘记
  }, [count]);  //数组依赖不要忘记
 
  return <div>{count}</div>;
}

方式二:使用useRef

function Index() {
  const savecallback=useRef(null); //为了避免形成闭包
  function callback(){
    // 可以调其他函数
    // 可以调接口
  }

  /*每当组件被重新渲染,useEffect 都会将最新的回调函数赋值给 ref.current,接着 ref.current会被放到 setInterval 里去执行。所以 setInterval 虽只在组件初始化时被启动了一次,但它在执行每次定时任务时,使用的都是最新的回调函数。回调函数不再被困于闭包当中,最新的 state、props 自然能够被取到。*/
  
  useEffect(() => {
    (savecallback as any).current = callback;
  });

  useEffect(() => {
    const timer = setInterval(() => {
      (savecallback as any).current();
    }, 1000);
    return () => clearInterval(timer);
  }, []);
 
  return <div>页面</div>;
}

方式三、使用useReducer 状态管理 (对于定时更新某个变量更友好,定时调接口的话还是上边两种更方便一点)

const intitstate= {count: 0};

function reducer(state = 0,action) {
  return {count: state.count + 1};
}
 
export default function Index() {
  const [state, dispatch] = useReducer(reducer,intitstate);
 
  useEffect(() => {
    setInterval(() => {
      dispatch();
    }, 1000);
  }, []);
 
  return <div>{state.count}</div>;
}

因为闭包的原因,回调函数无法取到最新的 state,而大多数场景下我们更新 state 前又必须先获取 state 的当前值。那如何才能够在不读取最新 state 的前提下,对 state 进行增量更新,可以用useReducer 状态管理。

资料参考:

usestate中的回调函数_React Hooks 中使用 setInterval 的若干方法_weixin_39771351的博客-CSDN博客

react+hooks的定时器问题_本宝宝很开心的博客-CSDN博客

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐