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>等表格原生元素的动画支持有限,可通过两种方式规避:- 用
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> - 在
<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
相关产品推荐
相关产品推荐

