React中Announcer组件多消息同时渲染问题求助
解决React宝可梦游戏Announcer组件消息逐次逐字显示问题
当前所有消息同时启动逐字动画的原因是每个AnnouncerMessage组件挂载后立刻触发自身动画逻辑,没有顺序控制。要实现逐个消息依次触发逐字效果,可以通过以下方案解决:
核心思路
给每个消息计算专属启动延迟,延迟时间等于前面所有消息的总字符数乘以单个字符的动画时长(25ms),确保前一个消息完全显示后,下一个才开始逐字渲染。
代码修改
1. 调整Announcer父组件
在父组件中计算每个消息的启动延迟,传递给子组件:
import AnnouncerMessage from "./AnnouncerMessage"; const Announcer = ({ messages }) => { // 计算每个消息的启动延迟 const calculateDelays = () => { let totalChars = 0; return messages.map(msg => { const delay = totalChars * 25; // 单个字符动画时长25ms totalChars += msg.length; return delay; }); }; const delays = calculateDelays(); return ( <div className="announcer"> <div className="announcerMessages"> {messages.map((msg, idx) => ( <AnnouncerMessage key={idx} message={msg} startDelay={delays[idx]} /> ))} </div> </div> ); }; export default Announcer;
2. 重构AnnouncerMessage子组件
接收启动延迟参数,优化动画逻辑并修复定时器泄漏问题:
import { useState, useEffect, useRef } from "react"; const AnnouncerMessage = ({ message, startDelay }) => { const [displayText, setDisplayText] = useState(""); const currentIndex = useRef(0); const timerRef = useRef(null); useEffect(() => { // 重置状态,避免消息更新时的残留问题 currentIndex.current = 0; setDisplayText(""); const startTyping = () => { const tick = () => { if (currentIndex.current <= message.length) { setDisplayText(message.slice(0, currentIndex.current)); currentIndex.current++; timerRef.current = setTimeout(tick, 25); } }; timerRef.current = setTimeout(tick, startDelay); }; startTyping(); // 组件卸载时清理定时器,防止内存泄漏 return () => { if (timerRef.current) { clearTimeout(timerRef.current); } }; }, [message, startDelay]); return <p>{displayText}</p>; }; export default AnnouncerMessage;
关键优化点
- 精准延迟控制:通过累计前置消息的总字符数,确保消息按顺序启动动画。
- 内存泄漏防护:添加组件卸载时的定时器清理逻辑,避免无效定时器占用资源。
- 状态重置机制:当消息内容或延迟参数变化时,重置动画状态,保证重新渲染的正确性。
- 规范列表渲染:给循环元素添加
key属性,符合React渲染规范,避免不必要的重渲染。
内容的提问来源于stack exchange,提问作者Saulo Andrade
相关产品推荐
相关产品推荐

