React useEffect未触发退出条件:打字机效果组件重复挂载问题
打字机效果的问题分析与修复
你的代码存在几个核心问题,导致组件不断重复更新甚至异常:
- 重复创建定时器:每次
word状态更新都会触发useEffect,而每次触发都会新建一个setInterval,旧的定时器没有被清理,最终多个定时器同时运行,导致组件频繁更新。 - 闭包捕获旧值:定时器回调里的
word是创建定时器时的闭包值,不是最新的状态,会导致setWord更新错误。 - 无清理逻辑:既没有在组件卸载时清除定时器,也没有在打字完成后终止定时器。
下面是修复后的代码:
import { useState, useEffect, useRef } from 'react'; export default function Typewriter() { const name: string = 'Mouhib Ouni'; const [word, setWord] = useState<string>(''); // 用useRef保存定时器ID,方便后续清理 const timerRef = useRef<NodeJS.Timeout | null>(null); useEffect(() => { // 只在组件挂载时初始化一次定时器 timerRef.current = setInterval(() => { // 使用函数式更新获取最新的word状态 setWord(prevWord => { if (prevWord.length >= name.length) { // 打字完成后清除定时器 clearInterval(timerRef.current!); return prevWord; } return prevWord + name[prevWord.length]; }); }, 1000); // 组件卸载时清理定时器 return () => { if (timerRef.current) { clearInterval(timerRef.current); } }; }, []); // 依赖项为空数组,仅执行一次 return <div>{word}</div>; }
关键改动说明:
useRef存储定时器ID:确保能在回调和清理函数中访问到同一个定时器实例,避免内存泄漏。- 函数式更新
setWord:通过prevWord获取最新的状态值,避免闭包带来的旧值问题。 - 单次初始化定时器:
useEffect依赖项为空数组,只在组件挂载时创建一次定时器,不会重复触发。 - 自动清理逻辑:打字完成后主动清除定时器,同时在组件卸载时也清理定时器,彻底避免无效更新。
内容的提问来源于stack exchange,提问作者mouhib
相关产品推荐
相关产品推荐

