React+iTyped打字动画运行时禁用点击触发的实现方案
解决React+iTyped打字动画运行时重复触发的问题(不使用useState)
因为不能用useState(避免重渲染),可以用useRef来维护一个动画运行状态的标记——ref的更新不会触发组件重渲染,完全符合需求。
具体实现步骤:
- 新增一个ref用于跟踪动画是否处于活跃状态:
const isAnimating = useRef(false);
- 修改触发动画的核心函数
typedFun,先判断状态,避免重复执行:
const typedFun = () => { // 如果动画正在运行,直接返回 if (isAnimating.current) return; // 标记动画开始 isAnimating.current = true; typedCaller2(); setTimeout(() => { typedCaller3(); }, 1000); }
- 给
typedCaller3(typedFun中最后执行的动画)添加onComplete回调,动画结束后重置状态:
const typedCaller3 = () => { init(textRef.current, { showCursor: false, backDelay: 1500, typeSpeed: 110, backSpeed: 75, loop: false, strings: ['hi', 'hello', 'goodbye'], // 动画完成后重置状态 onComplete: () => { isAnimating.current = false; } }) }
- 处理初始化的动画(
useEffect中的逻辑),同样维护状态:
useEffect(() => { isAnimating.current = true; setTimeout(() => { typedCaller4(); }, 2000); setTimeout(() => { typedCaller(); }, 5000); },[])
完整修改后的代码:
import { useRef, useEffect } from 'react'; import { init } from 'ityped'; // 假设Box和Description是你导入的组件 const YourComponent = () => { const textRef = useRef(); const isAnimating = useRef(false); const typedCaller = () => { init(textRef.current, { showCursor: false, backDelay: 1500, typeSpeed: 110, backSpeed: 75, loop: false, strings: ['test1', 'test2', 'test3'], onComplete: () => { isAnimating.current = false; } }) } const typedCaller2 = () => { init(textRef.current, { showCursor: false, loop: false, startDelay: 1, backDelay: 1, strings: [' ', ' '] }) } const typedCaller4 = () => { init(textRef.current, { showCursor: false, loop: false, backSpeed: 75, strings: [' ', ' '] }) } const typedCaller3 = () => { init(textRef.current, { showCursor: false, backDelay: 1500, typeSpeed: 110, backSpeed: 75, loop: false, strings: ['hi', 'hello', 'goodbye'], onComplete: () => { isAnimating.current = false; } }) } const typedFun = () => { if (isAnimating.current) return; isAnimating.current = true; typedCaller2(); setTimeout(() => { typedCaller3(); }, 1000); } useEffect(() => { isAnimating.current = true; setTimeout(() => { typedCaller4(); }, 2000); setTimeout(() => { typedCaller(); }, 5000); },[]) return( <Box> <Description className='SubText' onClick={typedFun} sx={{height: '30px', paddingBottom: '30px'}}> <span ref={textRef}></span> </Description> </Box> ) } export default YourComponent;
这样修改后,动画运行期间点击元素不会触发新的动画,只有等当前动画完全结束后,点击才会重新触发,而且全程没有使用useState,不会引发页面重渲染。
内容的提问来源于stack exchange,提问作者user20115099
相关产品推荐
相关产品推荐

