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

Framer Motion组件挂载/卸载时无动画问题求助

问题描述

使用Framer Motion为自定义表格行实现挂载动画时,动画未生效。已尝试将AnimatePresence作为motion组件的直接父组件并设置key值,但问题仍未解决。

相关代码

return (
  <>
    ...some code here
    {isExpanded && <AnimatePresence>{renderLinkedAccounts()}</AnimatePresence>}
  </>
);

const renderLinkedAccounts = () => linkdedAccounts.map((model, index) => (
    <motion.Tr
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        layout
        key={index}
    >
        <Td><span /></Td>
        <Td data-tooltip={model.getEmailAddress()}>
            {model.getEmailAddress()}
        </Td>
        <Td>
            {userType === 1 ? model.getAccountId() : model.getMailboxKey()}
        </Td>
        <Td>
            {getAccountType()}
        </Td>
        <Td>
            {getAccountStatus()}
        </Td>
        <Td>{getOutINStatus("outgoing")}</Td>
        <Td>{getOutINStatus("incoming")}</Td>
    </motion.Tr>
));
解决方法
  • 调整AnimatePresence的包裹逻辑
    当前写法中,AnimatePresence与内部motion组件同时被条件渲染,导致AnimatePresence无法捕捉到子组件的挂载事件。需将AnimatePresence放在条件判断外部,保持其始终存在:

    <AnimatePresence>
      {isExpanded && renderLinkedAccounts()}
    </AnimatePresence>
    
  • 替换不稳定的key值
    使用index作为key会在列表项变化时导致React复用组件,Framer Motion无法正确识别组件的挂载/卸载。改用model的唯一标识作为key:

    <motion.Tr
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        layout
        key={model.getAccountId()} // 优先使用model的唯一属性,如accountId
    >
    
  • 解决表格元素的动画兼容性
    部分浏览器对<tr>等表格原生元素的动画支持有限,可通过两种方式规避:

    1. 用motion.div模拟表格行(需配合CSS调整布局):
      <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          layout
          key={model.getAccountId()}
          style={{ display: 'table-row' }}
      >
          {/* 原Td内容 */}
      </motion.div>
      
    2. 在<tr>内部嵌套motion.div承载动画:
      <Tr>
          <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              layout
              style={{ display: 'table-cell', width: '100%' }}
          >
              {/* 原Td内容 */}
          </motion.div>
      </Tr>
      
  • 优化动画执行顺序(可选)
    若需批量渲染列表项的动画,给AnimatePresence添加mode="wait"属性,让动画按顺序触发:

    <AnimatePresence mode="wait">
      {isExpanded && renderLinkedAccounts()}
    </AnimatePresence>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:10:25