直接进入中心内容(重点): 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<number, string> = { 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 ( <div className="cur-time vertical-center"> <div className="cur-time-t">{getDate().hour}</div> <div className="cur-time-b"> <span className="">{getDate().day}</span> <div className="t-line" /> <span className="week">{getDate().week}</span> </div> </div> ); }; export default Timer;
解决方案二:两个setState 配合useEffect ,第一个 setState来控制 useEffect的依赖值,因为setInterval里面的第一个setState每次都会变化,所以每隔1S都会触发useEffect,然后在useEffect里面来更新 我们dom上面 需要用到的值就行了
代码:
import React, { useEffect, useRef, useState } from 'react'; import dayjs from 'dayjs'; const weeks: Record<number, string> = { 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 ( <div className="cur-time vertical-center"> <div className="cur-time-t">{getDate().hour}</div> <div className="cur-time-b"> <span className="">{getDate().day}</span> <div className="t-line" /> <span className="week">{getDate().week}</span> </div> </div> ); }; export default Timer;