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

如何让framer-motion在useState数组更新/重渲染时始终执行动画?

解决Framer Motion动画触发异常问题

核心问题本质

你遇到的问题是Framer Motion未正确识别元素的「进入状态变化」:

  • 从「All」切换到特定年份时,过滤后的元素实际已存在于DOM中(仅被隐藏),不会触发进入动画
  • 从特定年份切回「All」时,原有年份的元素未被标记为「重新进入」,仅新增元素触发动画

具体修复方案

1. 给元素key绑定筛选状态

不要使用固定的item.id作为唯一key,需将当前选中的年份也加入key,让Framer Motion识别每次筛选后都是全新的元素集合:

{filteredItems.map(item => (
  <motion.div
    key={`${item.id}-${selectedYear}`} // 结合item.id和选中年份生成唯一key
    initial={{ opacity: 0, scale: 0.5 }}
    animate={{ opacity: 1, scale: 1 }}
    exit={{ opacity: 0, scale: 0.5 }}
    transition={{ duration: 0.3 }}
    className="box"
  >
    {item.year} - {item.name}
  </motion.div>
))}

2. 确保列表被AnimatePresence包裹

AnimatePresence是Framer Motion处理动态列表动画的核心组件,必须用它包裹你的元素列表,才能跟踪元素的进入/退出状态:

<AnimatePresence>
  <div className="box-container">
    {filteredItems.map(item => (
      // 上述motion.div代码
    ))}
  </div>
</AnimatePresence>

3. 强制容器重新渲染(备选方案)

如果第一种方法仍不生效,可给列表容器添加key={selectedYear},强制每次切换年份时重新渲染整个列表:

<AnimatePresence>
  <div className="box-container" key={selectedYear}>
    {filteredItems.map(item => (
      <motion.div
        key={item.id}
        initial={{ opacity: 0, scale: 0.5 }}
        animate={{ opacity: 1, scale: 1 }}
        exit={{ opacity: 0, scale: 0.5 }}
        transition={{ duration: 0.3 }}
        className="box"
      >
        {item.year} - {item.name}
      </motion.div>
    ))}
  </div>
</AnimatePresence>

修复原理

  • 绑定筛选状态到key后,每次切换年份都会改变元素的唯一标识,Framer Motion会将其视为新元素,重新触发initial到animate的过渡动画
  • AnimatePresence负责监听DOM元素的添加/移除,确保进入和退出动画能被正确触发

内容的提问来源于stack exchange,提问作者magnus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 04:35:03