React使用Framer Motion时如何避免列表更新后触发initial属性动画
解决方案
根因说明
你删除完成后全量拉取列表数据,通过setFormations(res.data)直接替换整个状态数组,会让framer-motion误判未删除的现有列表项为新挂载元素,从而重复触发initial入场动画。
方案1(优先推荐):删除后前端直接更新状态,取消全量拉取
你已经明确知道被删除条目的id,无需额外调用接口拉取全量数据,直接过滤原有状态即可,既提升性能也不会触发现有条目的动画:
const handleDeleteFormation = async (id) => { await axios({ method: "DELETE", url: `http://localhost:1337/formations/${id}` }) // 直接过滤原有状态,不调用getFormations全量拉取 setFormations(prev => prev.filter(formation => formation.id !== id)) }
方案2:必须全量拉取时,给initial属性增加判断逻辑
如果存在多端同步数据等场景必须全量拉取最新列表,可以维护一个已渲染过的id集合,只有首次出现的条目才触发入场动画:
// 组件内声明ref存储已渲染过的id,避免状态更新触发重渲染 const renderedIds = useRef(new Set()) // 列表渲染部分修改为: <AnimatePresence exitBeforeEnter initial={false}> {formations && formations.map((formation) => <motion.div key={formation.id} // 已渲染过的条目直接跳过initial动画 initial={renderedIds.current.has(formation.id) ? false : { opacity: 0, x: -10 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -10 }} transition={{ type: "tween", ease: 'easeOut', duration: 0.2 }} // 入场动画完成后将id加入已渲染集合 onAnimationComplete={() => renderedIds.current.add(formation.id)} > ... </motion.div> )} </AnimatePresence>
额外检查项
确认AnimatePresence组件没有被设置动态变化的key属性,也不会随父组件重渲染被销毁重建,否则会导致内部所有motion.div被判定为新元素,重复触发入场动画。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

