直接进入中心内容(重点): 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 (
{getDate().hour}
{getDate().day}
{getDate().week}
);
};
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 = {
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 (
{getDate().hour}
{getDate().day}
{getDate().week}
);
};
export default Timer;