为点击筛选按钮的筛选项添加动画效果(修复异常问题)
问题排查与解决方案
问题根源
- 动画状态逻辑错误:当前用
anim布尔值翻转来控制动画类,每次点击按钮都会切换状态——第一次点击添加动画类,第二次点击移除,导致出现「有动画→无内容→有动画」的交替现象(推测你的CSS中fil-item默认隐藏,仅fil-item-active才显示并执行动画)。 - 状态不同步:筛选数据和动画状态的更新没有配合,动画触发逻辑依赖手动翻转状态,而非数据变化的时机。
修复方案
我们需要每次筛选数据变化时强制触发一次完整的动画流程,而非简单切换布尔状态。以下是修改后的代码:
import React, { useState, useEffect } from 'react'; import suggestData from '../data/suggest-data.json'; const allCategories = ['All', ...new Set(suggestData.map(item => item.area))]; const Suggest = () => { const [suggestItem, setSuggestItem] = useState(suggestData); const [selectedIndex, setSelectedIndex] = useState(0); const [isAnimating, setIsAnimating] = useState(false); const filter = (button) => { let filteredData = suggestData; if (button !== 'All') { filteredData = suggestData.filter(item => item.area === button); } setSuggestItem(filteredData); } // 监听筛选数据变化,自动触发动画 useEffect(() => { // 触发动画:添加动画类 setIsAnimating(true); // 动画结束后移除类(时长需和你的CSS动画时长匹配) const timer = setTimeout(() => { setIsAnimating(false); }, 500); return () => clearTimeout(timer); }, [suggestItem]); return ( <div> <h1>Suggest</h1> <div className="fil"> <div className="fil-btns"> <div className="fil-btn"> <button className='btn'>Hello</button> {allCategories.map((cat, index) => ( <button type="button" key={index} onClick={() => { filter(cat); setSelectedIndex(index); }} className={`btn ${selectedIndex === index ? "btn-active" : ""}`} > {cat} </button> ))} </div> </div> <div className="fil-items"> {suggestItem.map((item, index) => ( <div className={`fil-item ${isAnimating ? "fil-item-active" : ""}`} key={item.id || index} {/* 优先用数据唯一ID作为key,避免DOM复用问题 */} > <h1>{item.name}</h1> <h2>{item.category}</h2> <h3>{item.location}</h3> <h4>{item.type}</h4> <h5>{item.area}</h5> </div> ))} </div> </div> </div> ); } export default Suggest;
额外优化说明
- 移除了无用的
butto状态,直接用allCategories渲染按钮,简化代码。 - 优化
filter函数逻辑,减少分支判断。 - 建议用数据的唯一标识(如
item.id)代替index作为列表key,避免React列表渲染时的DOM复用问题,确保动画正常触发。 - 定时器时长需与你的CSS动画时长匹配,示例中假设动画时长为500ms。
参考CSS样式
确保动画类的样式逻辑正确,示例如下:
.fil-item { opacity: 0; transform: translateY(20px); transition: all 0.5s ease; } .fil-item-active { opacity: 1; transform: translateY(0); }
内容的提问来源于stack exchange,提问作者Mahabub Hossain
相关产品推荐
相关产品推荐

