React Native实现带动画逐个删除数组元素的问题与方案
无限循环的根本原因
React 函数组件里的state在单次渲染周期内是闭包冻结的常量,且setState的状态更新是异步批量执行的:
- 你写的
while是同步阻塞循环,整个循环执行过程中函数组件根本不会重新渲染,循环体内读到的taskItems永远是本次删除函数执行时拿到的初始状态值,长度从头到尾不会变,循环终止条件永远不满足,直接触发死循环。 - 你注释掉的空
setTimeout没有任何实际作用,同步循环会在一瞬间跑完成百上千次setTaskItems调用,React最终只会批量处理最后一次更新,既不会有逐个删除的效果,也解决不了死循环问题。
逐个删除带动画的实现方案
不要用同步循环硬卡执行节奏,改用「异步递归+函数式状态更新」的写法,每次删除后等待动画时长跑完、视图更新完成,再执行下一次删除:
const handleClearAll = () => { // 记录初始总任务数,确定递归终止条件 const totalTaskNum = taskItems.length; let deletedNum = 0; const removeLastOne = () => { // 用函数式更新,永远拿到上一次更新后的最新state,不依赖闭包旧值 setTaskItems(prevItems => { if (prevItems.length === 0) return prevItems; // 移除最后一项 return prevItems.slice(0, -1); }); deletedNum += 1; // 没删完就等待对应动画时长后再删下一个,时长和你列表项的退出动画保持一致即可 if (deletedNum < totalTaskNum) { setTimeout(removeLastOne, 180); } }; removeLastOne(); };
如果要更流畅的视觉效果,可以搭配React Native内置的Animated库或者react-native-reanimated,给每个待办项加透明度、位移的退出动画,等动画执行完成后再移除对应数组项,比单纯定时删除的体验好很多。
注意:所有需要基于前一个状态计算新状态的setState场景,都优先用函数式更新写法,避免闭包拿到旧state导致的逻辑错误。
内容的提问来源于stack exchange,提问作者yem
相关产品推荐
相关产品推荐

