React Spring translate动画不生效、列表项点击延迟问题求解
问题根因
- 状态更新异步导致参数错误:React中setState为异步批量更新逻辑,你在点击回调中更新
currentIndex、previousIndex后立即调用fn()获取动画参数,此时读取的两个索引仍是更新前的旧值,导致首次点击的动画配置错误,需要第二次点击才能拿到上一次更新的正确索引。 - 高亮条渲染逻辑错误:你将
animated.div放在选项循环内部,且添加了currentIndex === index的条件判断,每次切换选中项时,旧位置的高亮条会直接被卸载,新位置的高亮条重新挂载,不会触发过渡动画,只会直接显隐。 - react-spring用法错误:无需将
useSpring的返回值包裹在useState中,useSpring本身会返回响应式的动画样式对象以及更新动画的API方法,自行用useState包裹会打断动画状态的响应式更新链路。
修复后代码
import { useSpring, animated } from '@react-spring/web' import { useState } from 'react' import TextWithIcon from './TextWithIcon' // 示例options结构,可根据实际业务调整 const options = [ { name: 'Option 1', filledIcon: <>填充实例1</>, outlineIcon: <>线框实例1</> }, { name: 'Option 2', filledIcon: <>填充实例2</>, outlineIcon: <>线框实例2</> }, { name: 'Option 3', filledIcon: <>填充实例3</>, outlineIcon: <>线框实例3</> }, ] const Menu = () => { const [currentIndex, setCurrentIndex] = useState<number>(0) // 正确使用useSpring,返回动画样式和更新API const [spring, api] = useSpring(() => ({ transform: `translateY(0px)`, })) const onClick = (name: string, index: number) => { setCurrentIndex(index) // 直接用点击传入的index计算目标位置,不依赖异步更新的state api.start({ transform: `translateY(${index * 52}px)`, }) } return ( {/* 外层容器添加相对定位,作为高亮条的定位父级 */} <div style={{ position: 'relative' }}> {/* 高亮条移出循环,仅渲染一次,靠translateY实现滑动 */} <animated.div style={{ ...spring, background: 'orange', height: 52, width: '100%', position: 'absolute', left: 0, zIndex: 1 }} /> {options.map((option, index) => ( <div key={option.name} onClick={() => onClick(option.name, index)} {/* 选项层级高于高亮条,避免文字被遮挡 */} style={{ height: 52, position: 'relative', zIndex: 2 }} > <TextWithIcon icon={currentIndex === index ? option.filledIcon : option.outlineIcon} text={option.name} /> </div> ))} </div> ) } export default Menu
TextWithIcon组件本身逻辑无问题,无需修改。
内容的提问来源于stack exchange,提问作者user2387766
相关产品推荐
相关产品推荐

