React实现点击删除按钮后10秒内切换撤销按钮的方法
实现方案
核心逻辑是把「立即删除」改成「延迟确认删除」,拆分几个步骤做就行:
- 给每个列表项增加待删除标记、剩余倒计时字段,不要点击删除就直接把数据从列表移除
- 点击删除时只标记对应条目为待删除状态,启动10秒倒计时,倒计时期间条目保留在列表里,按钮切换为撤销按钮
- 倒计时每秒更新剩余时长,归零时才真正执行数据删除逻辑,同时清除定时器
- 点击撤销按钮时,清除对应条目的定时器,移除待删除标记,终止删除流程
- 所有定时器要在组件卸载、条目被删除/撤销时及时清理,避免内存泄漏
核心改造代码
import { useState, useRef, useEffect } from 'react' import Checkbox from './Checkbox' // 项目原有Checkbox组件 function App() { const [items, setItems] = useState([]) // 原有items状态 // 用ref存储所有定时器id,避免重复创建、方便统一清理 const timerRef = useRef({}) // 组件卸载时清掉所有残留定时器 useEffect(() => { return () => { Object.values(timerRef.current).forEach(clearInterval) } }, []) // 改后的删除触发方法:不直接删,先标记待删除 const triggerDelete = (itemId) => { // 标记对应条目为待删除,初始化10秒倒计时 setItems(prev => prev.map(item => { if (item.id === itemId) { return { ...item, isPendingDelete: true, countdown: 10 } } return item })) // 启动倒计时定时器 timerRef.current[itemId] = setInterval(() => { setItems(prev => { const target = prev.find(item => item.id === itemId) // 找不到条目说明已经被处理,直接清定时器 if (!target) { clearInterval(timerRef.current[itemId]) delete timerRef.current[itemId] return prev } // 倒计时归零,执行真正删除 if (target.countdown <= 1) { clearInterval(timerRef.current[itemId]) delete timerRef.current[itemId] return prev.filter(item => item.id !== itemId) } // 倒计时减1秒 return prev.map(item => { if (item.id === itemId) { return { ...item, countdown: item.countdown - 1 } } return item }) }) }, 1000) } // 撤销删除方法 const undoDelete = (itemId) => { // 清掉对应定时器 clearInterval(timerRef.current[itemId]) delete timerRef.current[itemId] // 移除待删除标记 setItems(prev => prev.map(item => { if (item.id === itemId) { return { ...item, isPendingDelete: false, countdown: 0 } } return item })) } // 原有勾选逻辑 const onChangeBox = (targetItem) => { setItems(prev => prev.map(item => { if (item.id === targetItem.id) { return { ...item, done: !item.done } } return item })) } return ( <div> <ul> {items.map((item) => { return ( <li key={item.id} style={{ textDecoration: item.done ? "line-through" : null, opacity: item.isPendingDelete ? 0.5 : 1 // 待删除条目加半透明提示 }} > <Checkbox onClick={() => onChangeBox(item)} defaultChecked={item.done} disabled={item.isPendingDelete} // 待删除时禁用勾选,避免交互冲突 /> {item.value}{" "} { item.isPendingDelete ? ( <button className="undo-button" onClick={() => undoDelete(item.id)} > 撤销删除({item.countdown}s) </button> ) : ( <button className="del-button" onClick={() => triggerDelete(item.id)} > ❌ </button> ) } </li> ); })} </ul> </div> ); } export default App;
可选优化点
- 待删除的条目可以加红色边框、浅红背景等更明显的视觉提示
- 倒计时最后3秒可以把数字标红,强化用户感知
- 这套逻辑天然支持多条目同时触发删除,每个条目独立维护自己的定时器和倒计时,不会互相干扰
内容的提问来源于stack exchange,提问作者banzawarrior
相关产品推荐
相关产品推荐

