You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 11:39:00