直接进入中心内容(重点): settimeOut和setInterval的函数无法获取外层setState值的问题(闭包,无法以及匿名函数获取到外面的值 )
记得以前没用箭头函数和 hook的时候一般会把this 指定程_this, 但是hook和匿名函数 没有this,所以需要另外解决
解决方案1:使用 ref 来 代理一层 就能获取到,ref的current是一个能实时变化的全局变量,函数里面 setState就行了
import React, { useEffect, useRef, useState } from 'react'; import dayjs from 'dayjs'; const weeks: Record= { 0: '星期天', 1: '星期一', 2: '星期二', 3: '星期三', 4: '星期四', 5: '星期五', 6: '星期六', }; const Timer = () => { const [curTime, setCurTime] = useState(dayjs().valueOf()); // console.log('getCurTime', curTime); const timeRef: any = useRef(); const getDate = () => { if (!curTime) { return { day: '', hour: '', week: '', }; } const day = dayjs(curTime).format('YYYY/MM/DD'); const hour = dayjs(curTime).format('hh:mm:ss'); const week = weeks[dayjs(curTime).day()]; return { day, hour, week, }; }; const callback = () => { setCurTime(dayjs().valueOf()); }; useEffect(() => { timeRef.current = callback; const timer = setInterval(() => { timeRef.current(); }, 1000); return () => { clearInterval(timer); }; }, []); return ( ); }; export default Timer;{getDate().hour}{getDate().day} {getDate().week}
解决方案二:两个setState 配合useEffect ,第一个 setState来控制 useEffect的依赖值,因为setInterval里面的第一个setState每次都会变化,所以每隔1S都会触发useEffect,然后在useEffect里面来更新 我们dom上面 需要用到的值就行了
代码:
import React, { useEffect, useRef, useState } from 'react'; import dayjs from 'dayjs'; const weeks: Record= { 0: '星期天', 1: '星期一', 2: '星期二', 3: '星期三', 4: '星期四', 5: '星期五', 6: '星期六', }; const Timer = () => { const [curTime, setCurTime] = useState(dayjs().valueOf()); const [newValue, setNewValue] = useState(0); const getDate = () => { if (!curTime) { return { day: '', hour: '', week: '', }; } const day = dayjs(curTime).format('YYYY/MM/DD'); const hour = dayjs(curTime).format('hh:mm:ss'); const week = weeks[dayjs(curTime).day()]; return { day, hour, week, }; }; useEffect(() => { setCurTime(dayjs().valueOf()); const timer = setTimeout(() => { setNewValue(newValue + 1); }, 1000); return () => { clearTimeout(timer); }; }, [newValue]); return ( ); }; export default Timer;{getDate().hour}{getDate().day} {getDate().week}