Inertia/React中useForm删除后tr元素动画异常问题
问题分析与解决方案
问题根源
你直接操作DOM元素的方式和React的声明式渲染机制冲突了:
- 调用
setMessage会触发组件重新渲染,此时React会根据删除后的users数据重新生成表格DOM - 你提前保存的
tr引用指向的是旧DOM节点,组件重新渲染后这个节点已经被React替换,导致动画错误地应用到了新渲染出的下一行上
修复方案
改用React状态管理来标记要删除的行,让React控制动画类的添加和DOM更新:
- 添加状态标记要删除的用户ID
const UsersContent = ({ users, flash }) => { const { delete: formDelete } = useForm(); const [message, setMessage] = useState(flash.message); // 添加状态:记录正在删除的用户ID const [deletingUserId, setDeletingUserId] = useState(null); // 原有的useEffect代码不变 useEffect(() => { const timer = setTimeout(() => { setMessage(null); }, 3000); return () => clearTimeout(timer); }, [message]); const handleSubmit = (e) => { e.preventDefault(); const userId = e.target.id; formDelete(route('users.destroy', userId), { onSuccess: () => { // 标记当前要删除的用户,由React给对应tr加动画类 setDeletingUserId(userId); setMessage({ tipo: 'success', testo: `Utente ${userId} cancellato correttamente` }); // 动画结束后,重置标记(如果Inertia未自动刷新数据,可手动过滤本地users) setTimeout(() => { setDeletingUserId(null); // 若users是本地状态,可手动移除: // setUsers(prev => prev.filter(u => u.id !== userId)); }, 2000); }, onError: () => { setMessage({ tipo: 'danger', testo: `Errore durante la cancellazione dell'utente ${userId}` }); } }); } // 渲染表格时根据状态添加动画类 return ( <table> <tbody> {users.map(user => ( <tr key={user.id} className={deletingUserId === user.id ? 'fadeout' : ''} > {/* 表格内容 */} <td> <form onSubmit={handleSubmit} id={user.id}> <button type="submit">删除</button> </form> </td> </tr> ))} </tbody> </table> ); }
- 关键说明
- 利用React的状态驱动渲染,让
tr的fadeout类由deletingUserId状态控制,避免直接操作DOM - 动画结束后,要么等待Inertia自动刷新页面props(删除后的users数据),要么手动过滤本地users状态(如果是本地维护的)
- 确保每个
tr都有唯一的key(用user.id),让React能准确识别DOM节点,避免渲染混乱
为什么原代码失效?
React是声明式框架,组件渲染完全依赖状态/ props。当你调用setMessage更新状态时,组件会重新渲染,此时原来的tr DOM节点已经被React销毁并替换为新的DOM结构,你之前保存的tr引用已经无效,导致动画被错误地应用到了新的DOM节点上。
内容的提问来源于stack exchange,提问作者Vinx
相关产品推荐
相关产品推荐

