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

如何确保元素从数组移除前先执行CSS淡出动画?

问题解决:元素移除前执行淡出动画

问题核心

你当前的代码里,在触发淡出类的同时立刻调用setData把元素从数组中移除了——React会直接卸载这个Item组件,动画还没来得及执行就被清理了,自然看不到效果。

解决方案思路

把「添加淡出类」和「移除元素」拆成两步:先给元素加淡出类让动画完整执行,等动画结束后再从数组里删掉这个元素。

修改后的完整代码

父组件(Items.jsx)

function Items() {
    const [data, setData] = useState([]);
    const [removingItemId, setRemovingItemId] = useState(null);
    
    useEffect(() => {
        // 替换成你的实际API请求逻辑
        fetch('/your-api-url')
            .then(res => res.json())
            .then(response => setData(response));
    }, []);

    // 处理移除逻辑:先标记要移除的元素,等动画跑完再删
    const handleRemove = (itemId) => {
        setRemovingItemId(itemId);
        // 动画时长是0.3s,所以等300ms后更新数据
        setTimeout(() => {
            setData(prev => prev.filter(item => item.id !== itemId));
            setRemovingItemId(null);
        }, 300);
    };

    return (
        <div className="items">
            {data.map(item => (
                <Item 
                    key={item.id}
                    item={item}
                    isRemoving={item.id === removingItemId}
                    onRemove={() => handleRemove(item.id)}
                />
            ))}
        </div>
     )
}

export default Items;

子组件(Item.jsx)

function Item({ item, isRemoving, onRemove }) {
    useEffect(() => {
        const endTime = new Date(item.endTime);
        const checkExpired = () => {
            const now = new Date();
            const remainingSeconds = Math.floor((endTime.getTime() - now.getTime()) / 1000);
            
            if (remainingSeconds < 0) {
                onRemove();
            }
        };

        const intervalId = setInterval(checkExpired, 1000);
        return () => clearInterval(intervalId);
    }, [item, onRemove]);

    return(
        <div className={`item ${isRemoving ? 'item--fadeout' : ''}`}>
            {item.title}
        </div>
    )
}

export default Item;

SCSS样式

.item {
    border-bottom: 1px solid #e5e5e5;
    overflow: hidden;
    clear: both;
    // 用过渡代替动画更简洁,效果一致
    transition: opacity 0.3s linear;

    &--fadeout {
        opacity: 0;
    }
}

// 如果偏好使用动画,也可以保留这段(上面的transition可以删掉)
// @keyframes fadeout {
//     0% { opacity: 1; }
//     100% { opacity: 0; }
// }
// .item--fadeout {
//     animation: fadeout 0.3s linear forwards;
// }

关键调整点

  1. 数据流优化:子组件不再直接操作父组件的data状态,而是通过回调通知父组件处理移除,符合React单向数据流原则,代码更易维护。
  2. 时序控制:用setTimeout等待动画完全执行后再更新数组,确保用户能完整看到淡出效果。
  3. 样式修正:去掉了动画里的display: none——这个属性无法被动画过渡,而且组件最终会被React卸载,不需要CSS控制显示隐藏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 22:10:53