我正在使用 dnd-kit 并遇到问题! 当我将可拖动的元素与列表中的任何第一个元素(上方或下方)交换时,它工作正常,但如果我继续拖动并与以下元素交换,则排序行为会很奇怪。
这是列表项的代码:
import React, { useState } from "react";
import "./FieldTokenComponent.scss";
import { TokenData } from "../../../classes/TokenClasses/TokenCreator";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
export interface FieldTokenData {
tokenData: TokenData;
}
export default function FieldTokenComponent(props: FieldTokenData) {
const { tokenData } = props;
const {
tokenLabelColor,
tokenAlias,
tokenDefense,
tokenHP,
tokenInitiative,
tokenSpeed,
tokenType,
id,
} = tokenData;
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id: id });
const style = {
transition,
transform: CSS.Transform.toString(transform),
backgroundColor: `${tokenEliminated ? "gray" : tokenLabelColor}`,
};
return (
<div>
<div
id="battlefieldToken"
data-type={tokenType}
style={style}
ref={setNodeRef}
{...attributes}
{...listeners}
>
<span className="tokenInitiative">{tokenInitiative}</span>
<i className={`fa-solid fa-skull deathStatusIcon`}></i>
</span>
<span className="tokenName">{tokenAlias}</span>
<button onClick={expandToken} className="tokenExpandButton">
<i className="fa-solid fa-angle-down expandArrow"></i>
</button>
</div>
</div>
);
}
这是列表容器的代码:
import "./BattlefieldComponent.scss";
import TokenModal from "../../UIComponents/AddTokenModal/TokenModal";
import { useState } from "react";
import { DndContext, DragEndEvent } from "@dnd-kit/core";
import { closestCenter } from "@dnd-kit/core";
import { TokenData } from "../../../classes/TokenClasses/TokenCreator";
import FieldTokenComponent from "../../TokenComponents/FieldTokenComponent/FieldTokenComponent";
import {
SortableContext,
arrayMove,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
export function BattlefieldComponent() {
const [creaturesTokens, setCreaturesToken] = useState<
{ data: TokenData; id: number }[]
>([]);
function onDragEnd(event: DragEndEvent) {
const { active, over } = event;
console.log(event);
if (active.id !== over!.id) {
setCreaturesToken((tokens) => {
const newIndex = tokens.findIndex((token) => token.id === active.id);
const oldIndex = tokens.findIndex((token) => token.id === over!.id);
return arrayMove(tokens, oldIndex, newIndex);
});
}
}
return (
<div className="battlefieldZone">
<div className="battlefieldCol" id="creaturesCol">
<header>
<h3>CREATURES</h3>
</header>
<main className="battlefieldRow">
<DndContext collisionDetection={closestCenter} onDragEnd={onDragEnd}>
<SortableContext
items={creaturesTokens}
strategy={verticalListSortingStrategy}
>
{creaturesTokens.map((tokenData) => (
<FieldTokenComponent
tokenData={tokenData.data}
key={tokenData.data.tokenId}
/>
))}
</SortableContext>
</DndContext>
</main>
<TokenModal
tokenType="creaturesToken"
addToken={setCreaturesToken}
key="creaturesTokenModal"
/>
</div>
</div>
);
}
TokenModal 是我添加可拖动元素的,我不确定是否需要在此处添加此代码,所以请告诉我您是否认为相关。
您应该在 FieldTokenComponent 和 useSortable({ id: id }) 中使用与 key
相同的 id家长:
<FieldTokenComponent
tokenData={tokenData.data}
key={tokenData.data.tokenId}
/>
孩子:
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id: id });