我映射了一组实体,并为每个实体启动了不同的计时器。但是当时间到期时,两者都会重置(执行时间到的回调函数),但您希望其他计时器继续运行,直到时间用完。我使用了 useRef() 但它没有帮助。请告诉我我做错了什么
const ParentComp = () => <div>
{
items.map((el, i) => <ChildComp endTimeCb={}/>)
}
</div>
const ChildComp = ({endTimeCb}) => {
const timeoutId: any = useRef();
const [isRunning, setIsRunning] = useState(true);
useEffect(() => {
console.log('use', isRunning, minutesDiff)
if (isRunning) {
timeoutId.current = setInterval(() => {
setCurrentDate(() => {
console.log(minutesDiff)
if (minutesDiff < 0) {
endTimeCb && endTimeCb();
setIsRunning(false);
}
return new Date().getTime();
})
}, 1000);
return () => clearInterval(timeoutId);
} else {
console.log('cb')
endTimeCb();
}
}, [isRunning, minutesDiff, endTimeCb]);
return <></>
}
使用clearInterval(timeoutId.current):应使用timeoutId.current清除间隔以正确访问间隔ID。
每个组件单独的间隔:由于 useRef 为 ChildComp 的每个实例提供稳定的引用,因此每个组件实例将有自己的间隔 ID,从而防止实例之间的意外干扰。
卸载时正确清理:确保组件卸载时清除间隔,以避免潜在的内存泄漏或意外行为。
useEffect 中的依赖数组:确保依赖数组仅包含必要的依赖项。在这种情况下,包括 isRunning 和 endTimeCb,而 分钟Diff 应在间隔函数内计算。
ParentComp 中的 Key Prop:在映射时为每个子组件使用唯一的键,以确保 React 正确识别每个组件实例。在这里,我使用索引 i 作为键,但如果项目中有唯一标识符,最好使用它。
const ParentComp = () => {
const items = [];
return (
<div>
{items.map((el, i) => (
<ChildComp key={i} endTimeCb={() => console.log(`Timer ${i}ended`)}/>
))}
</div>
);
};
const ChildComp = ({ endTimeCb }) => {
const timeoutId = useRef(null);
const [isRunning, setIsRunning] = useState(true);
const [currentDate, setCurrentDate] = useState(new Date().getTime());
useEffect(() => {
if (isRunning) {
timeoutId.current = setInterval(() => {
setCurrentDate((prevDate) => {
const minutesDiff = /* calculate the difference in minutes here */;
if (minutesDiff < 0) {
setIsRunning(false);
endTimeCb && endTimeCb();
clearInterval(timeoutId.current); // Clear the interval here
}
return new Date().getTime();
});
}, 1000);
}
return () => clearInterval(timeoutId.current);//Cleanup interval on unmount
}, [isRunning, endTimeCb]);
return <></>;
};