React多表单场景:无useRef实现输入停止后延迟更新State
解决方案:实现输入防抖避免Quill组件卡顿(不使用useRef)
原代码存在的问题
- 实时更新状态触发频繁渲染:
handleDescription中每次输入都调用setEditors,直接触发组件重渲染,这是导致Quill卡顿的核心原因。 - 闭包导致状态无法更新:
useEffect的依赖数组为空,内部setInterval捕获的call、currentIndex、editors都是组件初始化时的旧值,后续状态更新后无法读取最新数据,逻辑完全失效。 - 未清除重复定时器:每次输入都会创建新的
setTimeout,旧定时器未被清除,会导致多次触发setCall(true),逻辑混乱。
修正后的实现代码
const [pendingUpdate, setPendingUpdate] = useState<{ index: number; value: any } | null>(null); const [editors, setEditors] = useState({}); const handleDescription = (e: any, index: number) => { // 记录最新的输入内容和索引 setPendingUpdate({ index, value: e }); }; // 利用useEffect监听pendingUpdate变化,实现防抖逻辑 useEffect(() => { if (!pendingUpdate) return; // 设置2秒后执行更新 const timer = setTimeout(() => { const { index, value } = pendingUpdate; // 更新状态 setEditors(prev => ({ ...prev, [index]: value })); // 调用目标函数 Work.Description(props, index, value); // 清空待更新标记 setPendingUpdate(null); }, 2000); // 组件重新渲染(或pendingUpdate变化)时,清除之前的定时器 return () => clearTimeout(timer); }, [pendingUpdate, props]); return ( <Container> <Items> {props.resume.employmentHistory.positions.map((position: any, index: number) => ( <Editor key={index} label="Description" value={position.description || ''} onChange={(e) => handleDescription(e, index)} /> ))} </Items> </Container> );
关键逻辑说明
- 用状态管理待更新内容:通过
pendingUpdate状态存储最新的输入值和索引,避免实时更新editors触发渲染。 - 防抖依赖useEffect实现:每次
pendingUpdate变化时,清除之前的定时器并重新设置,确保只有用户停止输入2秒后才执行最终的状态更新和函数调用。 - 避免闭包问题:
useEffect依赖pendingUpdate,每次状态变化都会重新创建定时器,内部能获取到最新的待更新数据。
内容的提问来源于stack exchange,提问作者nevoni3008
相关产品推荐
相关产品推荐

