首页 > 解决方案 > 使用 React 更改列表顺序的 CSS 动画

问题描述

在我的 React 应用程序中,我有一个“排名”页面。它有一个可以根据几个标准排序的列表。我想添加一个简单的 CSS 动画,以便在更改排序条件时,旧列表淡出和新排序列表淡入,而不是突然和立即更改。

我已经设法让列表在初始页面加载时进行动画处理。但是当排序标准改变时,列表会立即改变。我认为这可能是因为我不太了解 React 状态是如何工作的。非常感谢您的帮助 - 或指向可以澄清问题的手册的链接。

带走不必要代码的 JS:

function Ranking() {

const [items, setItems] = useState([]);
const [sortType, setSortType] = useState();
const [isSorted, setIsSorted] = useState();

// load items once on page load
useEffect(() => {
    loadItems();
}, [])

// fetch items from api
function loadItems() {
    fetch(
        `/api/get`,
        {
            method: "GET",
            mode: "cors"
        })
        .then((res) => res.json())
        .then((data) => {
            setItems((prevItems) => {
                return [...prevItems, ...data] })
                })
        .catch((error) => {
            console.log(error);
        });
}

// sort items based on current sort type
function sortItems(type) {
    console.log('starting sort...')
    setIsSorted(false);
    console.log('set isSorted to false: ', isSorted)
    if (type === 1) {
        return items.sort((a, b) => b.criteria1 - a.criteria1);
    } else if (type === 2) {
        return items.sort((a, b) => b.criteria2 - a.criteria2);
    } else if (type === 3) {
        return items.sort((a, b) => b.criteria3 - a.criteria3);
    };
}


// sort items on render
useEffect(() => {
    if (!sortType) {
        setSortType(1);
    }
    if (items.length > 0) {
        setItems(sortItems(sortType));
        setIsSorted(true);
    }
})

// when 'Criteria N' button is clicked, change sorting criteria accordingly
function handleSort(event) {
    const name = event.target.name;
    setIsSorted(() => {
        setSortType(parseInt(name));
        return false;
    });
}

return <div className="ranking-container">
            <button className="ranking-sort-btn" name="1" onClick={handleSort}>Criteria 1</button>
            <button className="ranking-sort-btn" name="2" onClick={handleSort}>Criteria 2</button>
            <button className="ranking-sort-btn" name="3" onClick={handleSort}>Criteria 3</button>
            <div className={isSorted ? "ranking-item-loaded" : "ranking-item-not-loaded"}>
                {items.map((item, index) => {
                        return <RankingItem item={item} key={index} isSorted={isSorted}/>   
                    })
                }
            </div>
       </div>

CSS:

.ranking-item-not-loaded {
    opacity: 0;
    transition: opacity 200ms ease-in;
}

.ranking-item-loaded {
    opacity: 1;
    transition: opacity 220ms ease-in;    
}

标签: javascriptcssreactjsstate

解决方案


事实证明,状态变化突然中断了转换。从过渡切换到不依赖第二状态的正确动画解决了这个问题。

<div className={isSorted && "ranking-item-animated"} onTransitionEnd={handleTransitionEnd}>
.ranking-item-animated {
    animation-duration: 1s;
    animation-name: fadein;
}

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

推荐阅读