如何使用react-spring实现记录列表入场动画?useTransition可在useEffect中调用吗?
问题解答
核心问题说明
- useTransition属于React Hook,必须遵循Hook调用规则,只能在组件顶层、自定义Hook内部调用,不能在useEffect、事件回调等非顶层作用域调用。
- 原代码没有动画效果是多个错误叠加导致的,逐一修正后即可实现从下到上逐个入场的效果。
原代码问题梳理
- 初始状态设置错误:初始state直接赋值了完整的列表数据,useEffect中又重复设置相同的数组,useTransition检测不到元素新增的过程,不会触发enter动画。
- 错误使用
Object.entries遍历数组:Object.entries是对象遍历方法,用在数组上会返回[索引, 元素]的嵌套结构,导致后续取item字段全部出错。 - 动画属性配置错误:没有配置位移相关属性,也没有添加逐个动画的间隔设置,无法实现从下到上依次出现的效果。
- 绝对定位设置冗余:所有元素都设置absolute会导致重叠,不需要额外设置定位即可实现效果。
修正后完整代码
import { useEffect, useState } from "react"; import { useTransition, animated } from "react-spring"; import "./styles.css"; const array1 = [ { id: "1", name: "Cat" }, { id: "2", name: "Dog" }, { id: "3", name: "Cow" } ]; export default function App() { // 初始设置为空数组 const [list, setList] = useState([]); const recordHeight = 40; // 组件挂载后再填充列表,触发入场动画 useEffect(() => { setList(array1); }, []); const transitions = useTransition(list, { // 配置元素唯一标识 keys: item => item.id, // 初始状态:透明度0,向下偏移30px from: { opacity: 0, translateY: 30, height: 0 }, // 入场状态:透明度1,回到正常位置 enter: { opacity: 1, translateY: 0, height: recordHeight }, leave: { opacity: 0 }, // 逐个动画的间隔时间,单位ms,数值越大间隔越久 trail: 150, config: { tension: 220, friction: 120 } }); return ( <div className="App"> {transitions((style, item) => ( <animated.div style={style} className="record" key={item.id}> <span>{item.name}</span> </animated.div> ))} </div> ); }
补充样式建议:给
.record添加overflow: hidden属性,避免高度动画过程中内容溢出。
内容的提问来源于stack exchange,提问作者soccerway
相关产品推荐
相关产品推荐

