React Card 示例问题 - 卡片被替换而不是附加到另一列中的卡片列表

React Card Example issue - Card is replaced instead of being appended to a list of cards in another column

我一直在努力解决这个问题,目标是拖动卡片形式 'Column 1' 并将其复制到另一列,比如 'Column 2'。 现在,当我的第一张卡片被拖放到“第 2 列”时,该卡片会相应地添加到该列,但是当我将另一张卡片拖放到 'Column 2' 而不是被附加时,它只是用自己替换现有卡片. 我一直在调试状态,但问题仍然存在。我不知道我在这里做错了什么?

这是我的代码

// Card Component
function Card({ id, text, isDrag }) {
  const [, drag] = useDrag(() => ({
    type: "bp-card",
    item: () => {
      return { id,  text}
    },
    collect: monitor => ({
      isDragging: !!monitor.isDragging(),
    }),
    canDrag: () => isDrag
  }));

  return (
    <div
      className='card'
      ref={drag}
      style={{
        cursor: isDrag ? 'pointer' : 'no-drop'
      }}
    >
      {text}
    </div>
  )
}

// Column Component
function Column({ title, children, onCardDropped }) {
  const [, drop] = useDrop(() => ({
    accept: "bp-card",
    drop: item => {
      onCardDropped(item);
    }
  }));

  return (
    <div className="flex-item" ref={title === 'Column 2' ? drop : null}>
      <p>{title}</p>

      {children.length > 0 && children.map(({ id, text, isDrag }) => (
        <Card
          key={id}
          id={id}
          text={text}
          isDrag={isDrag}
        />
      ))}
    </div>
  )
}

// Main App
function App() {
  const [cards] = useState([
    { id: 1, text: 'Card 1', isDrag: true },
    { id: 2, text: 'Card 2', isDrag: true },
  ]);

  const [columns, setColumns] = useState([
    {
      id: 1,
      title: 'Column 1',
      children: cards
    },
    {
      id: 2,
      title: 'Column 2',
      children: []
    },
  ]);

  const onCardDropped = ({ id, text }) => {
    // let card = null;
    const targetColumnId = 2;

    const transformedColumns = columns.map(column => {
      if (column.id === targetColumnId) {
        return {
          ...column,
          children: [
            ...column.children,
            { id, text }
          ]
        }
      }
      return column;
    });

    setColumns(transformedColumns);
  }

  return (
    <DndProvider backend={HTML5Backend}>
      <div className='flex-container'>
        {columns.map((column) => (
          <Column
            key={column.id}
            title={column.title}
            children={column.children}
            onCardDropped={onCardDropped}
          />
        ))}
      </div>
    </DndProvider>
  );
}

非常感谢任何帮助。谢谢

您需要使用设置状态方法的回调来考虑之前的状态。如下更改 onCardDropped 后它开始工作。

  const onCardDropped = ({ id, text }) => {
    // let card = null;
    const targetColumnId = 2;

    setColumns((prevColumns) =>
      prevColumns.map((column) => {
        if (column.id === targetColumnId) {
          return {
            ...column,
            children: [...column.children, { id, text }]
          };
        }
        return column;
      })
    );
  };

使用回调方法中的状态总是一个好主意,而不是直接使用可能过时的状态对象。

工作演示