为何添加新行时MotionButton先上浮再下沉?

我希望添加新行时按钮能平滑下移适配布局,因此给基于motion(...)包装的自定义组件MotionButton添加了layout属性。当前实现代码如下:
<div className="grid gap-5"> <AnimatePresence> {flightDates.map((f, index) => ( <motion.div key={index} exit={{ opacity: 0, y: 10, }} initial={{ opacity: 0, y: 10, }} animate={{ opacity: 1, y: 0, }} transition={{ duration: 0.2, }} > <FlightDateRow key={index} onChange={(updatedFlight) => { setFlightDates((prev) => { const newFlights = [...prev] newFlights[index] = { ...newFlights[index], ...updatedFlight, } return newFlights }) }} onDelete={removeFlightDate(index)} canDelete={flightDates.length > 1} {...f} /> </motion.div> ))} </AnimatePresence> <MotionButton className="w-min pl-2" variant="secondary" onClick={addNewFlightDate} layout transition={{ duration: 0.2, }} > <PlusMini className="mr-2" /> Flight </MotionButton> </div>
优化建议
- 替换列表key为唯一标识:当前用
index作为motion.div和FlightDateRow的key,在列表项增删时会导致React错误地复用组件,干扰动画和状态更新。建议改用每个航班日期对象的唯一ID(比如f.id)作为key。 - 确保MotionButton的layout属性生效:确认自定义的
MotionButton组件正确传递layout属性到底层motion元素,示例包装方式:const MotionButton = ({ children, ...props }) => ( <motion.button {...props}> {children} </motion.button> ); - 统一动画节奏:把过渡时长提取为常量,保持行和按钮的动画时长一致,提升交互流畅度。
修改后的代码示例:
const TRANSITION_DURATION = 0.2; <div className="grid gap-5"> <AnimatePresence> {flightDates.map((f) => ( <motion.div key={f.id} exit={{ opacity: 0, y: 10 }} initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: TRANSITION_DURATION }} > <FlightDateRow key={f.id} onChange={(updatedFlight) => { setFlightDates((prev) => prev.map(item => item.id === f.id ? {...item, ...updatedFlight} : item ) ); }} onDelete={removeFlightDate(f.id)} canDelete={flightDates.length > 1} {...f} /> </motion.div> ))} </AnimatePresence> <MotionButton className="w-min pl-2" variant="secondary" onClick={addNewFlightDate} layout transition={{ duration: TRANSITION_DURATION }} > <PlusMini className="mr-2" /> Flight </MotionButton> </div>
内容的提问来源于stack exchange,提问作者Stephen Horton
相关产品推荐
相关产品推荐

