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

React前置添加用户时CSS首元素动画仅首次生效的问题

解决前置添加用户时首项CSS动画仅触发一次的问题

问题描述

每次在列表前置添加新用户时,希望第一个<div>触发CSS淡入缩放动画,但当前代码仅第一次添加时动画生效,后续添加无效果。

原代码

JS代码

const [userList, setUserList] = useState<any>([]);
<div className='user-listing absolute top-0 left-0'>
    {
        userList.map((user:any, index:number)=>{
        return (
            <div key={index} className='user'>{user}</div>
        )
        })
    }
</div>
<button onClick={()=> setUserList((list:any) => [randomUser(),...list])}>
  add
</button>

SCSS代码

.user-listing{
  .user{
    &:first-child {
      animation-name: fadeIn;
      animation-duration: .15s;
    }
  }
}

@keyframes fadeIn {
  0% {
      opacity: 0;
      transform: scale(.2)
  }

  to {
      opacity: 1;
      transform: scale(1)
  }
}

问题原因

  1. 使用index作为key的缺陷:前置添加元素时,React会复用原有DOM节点(因为index重新排序后,新元素的key=0对应之前第一个元素的DOM),导致新元素并非全新渲染,不会触发:first-child的初始动画。
  2. CSS动画的触发机制:动画仅在元素首次应用样式时触发,复用DOM节点时元素已处于动画结束状态,不会重复执行。

解决方案

1. 改用唯一标识作为key

不要用index,给每个用户项分配唯一ID,确保新添加的用户会生成全新DOM节点。

2. 通过动态类名触发动画

利用状态记录需要动画的用户,添加动画类并在动画结束后移除,确保每次添加都能触发动画。

修改后的代码

JS代码(假设randomUser()返回带唯一ID的对象,若仅返回字符串可自行生成ID)

import { useState, useRef } from 'react';

const [userList, setUserList] = useState([]);
const animateUserId = useRef(null);

const addUser = () => {
  // 生成带唯一ID的用户(如果randomUser返回字符串,改为{ id: Date.now() + Math.random(), name: randomUser() })
  const newUser = randomUser();
  animateUserId.current = newUser.id;
  setUserList(prev => [newUser, ...prev]);
};

return (
  <>
    <div className='user-listing absolute top-0 left-0'>
      {userList.map((user) => {
        const needAnimate = user.id === animateUserId.current;
        return (
          <div 
            key={user.id} 
            className={`user ${needAnimate ? 'fade-in' : ''}`}
            onAnimationEnd={() => {
              if (needAnimate) animateUserId.current = null;
            }}
          >
            {user.name || user}
          </div>
        );
      })}
    </div>
    <button onClick={addUser}>add</button>
  </>
);

SCSS代码

.user-listing {
  .user {
    // 保留原有基础样式
  }

  .fade-in {
    animation: fadeIn .15s forwards;
  }
}

@keyframes fadeIn {
  0% {
    opacity: 0;
    transform: scale(.2);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

说明

  • 用用户唯一ID作为key,确保新前置的用户会渲染全新DOM元素。
  • 通过animateUserId记录当前需要动画的用户ID,动态添加fade-in类触发动画。
  • 监听animationEnd事件,动画结束后清除标识,避免后续渲染重复触发。

内容的提问来源于stack exchange,提问作者FeelRightz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 06:59:53