Я настойчиво работал над этой проблемой, цель которой состоит в том, чтобы перетащить карточку из «Столбца 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>
);
}
Любая помощь высоко ценится. Спасибо.
Вам нужно учитывать предыдущее состояние, используя обратный вызов метода set state. Он начинает работать после изменения 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;
})
);
};
Всегда полезно использовать состояние из метода обратного вызова, а не напрямую использовать объект состояния, который может быть устаревшим.
Рабочая демонстрация
Да. это работает так, как ожидалось! Это было прямо здесь. Спасибо, что разобрались.
@Mayur Prakash Upadhyay, посмотри!!