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

标签 reactjs react-dnd

我一直在坚持解决这个问题,目标是将卡片从“第 1 列”中拖动,然后将其复制到另一列“第 2 列”中。 现在,当我的第一张卡被拖放到“第 2 列”中时,该卡会相应地添加到该列中,但是当我拖动另一张卡并放入“第 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;
      })
    );
  };

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

工作演示

Edit cool-dew-8zl3s9

关于reactjs - React Card 示例问题 - 卡被替换而不是附加到另一列的卡列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72145364/

相关文章:

javascript - 将 React 与 Sublime 一起使用时出现问题

javascript - React Native 中的 TabBarICON 不起作用,项目相互重叠

testing - 如何在测试 react-dnd 时 stub 监视器?

reactjs - 通过单击并拖动一个角来调整 Material ui 卡组件的大小

reactjs - 在 reactjs 项目中构建服务层的普遍可接受的方式是什么?

javascript - Heroku "Invalid Host header"HOST 配置中的 ReactJS APP?

javascript - 如何在保留状态的同时复制组件?

drag-and-drop - react DnD - "Cannot have two HTML5 backends at the same time."

javascript - 用于测试 React 应用程序的全局导入

reactjs - Monitor.getDropResult() 返回 null