@dnd-kit 将可拖动元素与列表中超过 1 个元素交换时出现奇怪的排序行为

问题描述 投票:0回答:1

我正在使用 dnd-kit 并遇到问题! 当我将可拖动的元素与列表中的任何第一个元素(上方或下方)交换时,它工作正常,但如果我继续拖动并与以下元素交换,则排序行为会很奇怪。

让我给你看一下GIF: Link

这是列表项的代码:

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 是我添加可拖动元素的,我不确定是否需要在此处添加此代码,所以请告诉我您是否认为相关。

reactjs typescript drag-and-drop dnd-kit
1个回答
0
投票

您应该在 FieldTokenComponent 和 useSortable({ id: id }) 中使用与 key

相同的 id

家长:

<FieldTokenComponent
  tokenData={tokenData.data}
  key={tokenData.data.tokenId}
/>

孩子:

const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id: id });
© www.soinside.com 2019 - 2024. All rights reserved.