При создании списка подкачки в React я обнаружил странную ошибку перехода. Способ работы списка прост: вы нажимаете на элемент (A), его фон переходит на более светлый цвет, затем на другой (B), они меняются местами, и элемент A, теперь на новой позиции, переходит обратно к оригинальный цвет.
По крайней мере, так происходит, когда элемент A имеет более высокий индекс, чем элемент B. Когда все наоборот, переход после свопа обрезается.
Мне удалось найти обходной путь, используя window.requestAnimationFrame
, но он не идеален. Состояние перехода не сохраняется, что означает, что он всегда переходит обратно из полного светлого цвета. Здесь это не так важно, но это проблема моего другого проекта. Иногда переходы тоже обрезаются.
Код прост. Следует отметить, что элементы сохраняют свои ключи после замены. Я создал песочницу с кодом , чтобы вы могли поиграть.
import React, { useState } from "react";
const Item = props => {
let classes = "item";
if (props.selected) {
classes += " selected";
}
return (
<div className={classes} onClick={props.onClick}>
{props.value}
</div>
);
};
const App = () => {
const [list, setList] = useState([1, 2, 3]);
const [selected, setSelected] = useState(-1);
const select = index => {
setSelected(index);
};
const swap = index => {
const newList = [...list];
[newList[index], newList[selected]] = [newList[selected], newList[index]];
setList(newList);
setSelected(-1);
};
// The workaround that kind of works, but is not perfect.
// const swap = index => {
// const newList = [...list];
// [newList[index], newList[selected]] = [newList[selected], newList[index]];
// setList(newList);
// window.requestAnimationFrame(() => {
// setSelected(index);
// window.requestAnimationFrame(() => {
// setSelected(-1);
// });
// });
// };
const onClick = selected < 0 ? select : swap;
const items = list.map((value, index) => (
<Item
key={value}
value={value}
selected={selected === index}
onClick={onClick.bind(this, index)}
/>
));
return <div className="list">{items}</div>;
}
Вот ключевые правила CSS:
.item {
background: #0b7189; // darker
transition: background-color 1s;
}
.item.selected {
background-color: #228cdb; //lighter
}
Я ищу решение, более надежное, чем мой обходной путь.
Вся помощь будет оценена! :)