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;
})
);
};
使用回调方法中的状态总是一个好主意,而不是直接使用可能过时的状态对象。
工作演示
我一直在努力解决这个问题,目标是拖动卡片形式 '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;
})
);
};
使用回调方法中的状态总是一个好主意,而不是直接使用可能过时的状态对象。
工作演示