Может быть немного корявый но рабочий вариант, можно сделать проще если просто поле order местами менять и сортировать по нему
type MoveData = ((dir: "left" | "right", i: number) => void)
type TestItemProps = {
data: { name: string }, i: number, onMove: MoveData
}
const TestItem: FC<TestItemProps> = ({ data, i, onMove }) => {
return (
<div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{ cursor: "pointer" }}
onClick={() => onMove("left", i)}
>◀</span>
<span
style={{ cursor: "pointer" }}
onClick={() => onMove("right", i)}
>▶</span>
</div>
<span>{data.name}</span>
</div>
)
}
function Test() {
const [state, setState] = useState([
{ name: "Petya", order: 0 },
{ name: "Nikita", order: 1 },
{ name: "Sasha", order: 2 },
{ name: "Valera", order: 3 },
])
const onMoveHandle: MoveData = (dir, prev) => {
const isLeftBlock = prev === 0 && dir === "left"
const isRightBlock = prev === state.length - 1 && dir === "right"
if (isLeftBlock || isRightBlock) return
const next = dir === "left" ? prev - 1 : prev + 1
setState((past) => past.reduce((acc: { name: string, order: number }[], it, i, arr) => {
if (![prev, next].includes(i))
acc.push(it)
else {
if (i === prev) acc.push(arr[next])
else acc.push(arr[prev])
}
return acc
}, []))
}
return (
<div style={{ display: "flex", columnGap: "10px" }}>
{state.map((it, i) => (
<TestItem
data={it} i={i} onMove={onMoveHandle} key={i}
/>
))}
</div>
)
}