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

如何使用react-spring实现记录列表入场动画?useTransition可在useEffect中调用吗?

问题解答

核心问题说明

  • useTransition属于React Hook,必须遵循Hook调用规则,只能在组件顶层、自定义Hook内部调用,不能在useEffect、事件回调等非顶层作用域调用。
  • 原代码没有动画效果是多个错误叠加导致的,逐一修正后即可实现从下到上逐个入场的效果。

原代码问题梳理

  1. 初始状态设置错误:初始state直接赋值了完整的列表数据,useEffect中又重复设置相同的数组,useTransition检测不到元素新增的过程,不会触发enter动画。
  2. 错误使用Object.entries遍历数组:Object.entries是对象遍历方法,用在数组上会返回[索引, 元素]的嵌套结构,导致后续取item字段全部出错。
  3. 动画属性配置错误:没有配置位移相关属性,也没有添加逐个动画的间隔设置,无法实现从下到上依次出现的效果。
  4. 绝对定位设置冗余:所有元素都设置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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:27:04