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

React中实现数组filter筛选切换的淡入淡出过渡动画方案

分类切换淡入淡出效果实现

你之前用React Transition Group没生效,基本都是key设置错误、包裹层级不对、动画时长不匹配这几个原因,下面给两种可直接落地的实现方案:


方案1:React Transition Group 实现(支持单项目独立动画)

  1. 先确保依赖安装完成
npm i react-transition-group
# TS项目额外安装类型定义
npm i -D @types/react-transition-group
  1. 修改ProjectsUl组件,用TransitionGroup和CSSTransition包裹列表项,注意每个项必须绑定唯一key,不能用数组下标:
import { FC, useEffect, useState } from 'react';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
// 其余原有导入(ProjectsUlStyle、ProjectsLi、projects、IProject类型等)保持不变

export const ProjectsUl: FC<IProps> = ({ filter }) => {
  const [filtered, setFiltered] = useState<IProject[]>([])

  useEffect(() => {
    const filteredProjects = projects.filter((i) => i.category.includes(filter));
    setFiltered(filteredProjects);
  }, [filter]);

  return (
    <ProjectsUlStyle>
      {/* component={null} 表示TransitionGroup不渲染额外的DOM节点 */}
      <TransitionGroup component={null}>
        {filtered.map((item) => (
          <CSSTransition
            key={item.name} // 用项目名当唯一key,不要用数组index
            timeout={300} // 时长和CSS动画时长保持一致
            classNames="fade"
            unmountOnExit // 筛选移除的项直接卸载DOM,避免占位
          >
            <ProjectsLi filtered={item} />
          </CSSTransition>
        ))}
      </TransitionGroup>
    </ProjectsUlStyle>
  );
};
  1. 添加对应过渡样式,全局CSS或styled-components内编写均可:
/* 进入初始态、离开结束态 */
.fade-enter, .fade-exit-to {
  opacity: 0;
  transform: translateY(6px); /* 不需要位移效果直接删掉这行 */
}
/* 进入动画执行阶段、离开初始态 */
.fade-enter-active, .fade-exit {
  opacity: 1;
  transform: translateY(0);
  transition: all 300ms ease;
}
/* 动画完成稳定态 */
.fade-enter-done {
  opacity: 1;
  transform: translateY(0);
}

几个容易踩的坑:

  • timeout数值必须和CSS里transition的时长完全一致,否则会出现动画截断、元素显隐时机错乱
  • 不要手动给CSSTransition加in属性,TransitionGroup会自动管理子项的in状态
  • 如果项目名可能重复,建议给每个项目加单独的唯一id字段当key

方案2:纯CSS实现(无额外依赖,代码量极小)

如果不需要单个项目的独立进出动画,只是要整体切换的淡入效果,完全不用额外装库,几行代码就能搞定:

  1. 修改ProjectsUl组件,给列表容器绑定和当前筛选值关联的key,切换筛选时React会重新挂载容器触发动画:
export const ProjectsUl: FC<IProps> = ({ filter }) => {
  const [filtered, setFiltered] = useState<IProject[]>([])

  useEffect(() => {
    const filteredProjects = projects.filter((i) => i.category.includes(filter));
    setFiltered(filteredProjects);
  }, [filter]);

  return (
    <ProjectsUlStyle key={filter} className="project-list-fade">
      {filtered.map((item) => (
        <ProjectsLi filtered={item} key={item.name} />
      ))}
    </ProjectsUlStyle>
  );
};
  1. 添加CSS动画:
.project-list-fade {
  animation: listFadeIn 300ms ease forwards;
}

@keyframes listFadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

这个方案的效果是切换分类时整个列表整体淡入,实现成本最低,满足绝大多数简单场景的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:00:58