I'm working on a page builder of sorts for my product, and I'm using react-dnd
to accomplish what I need. So far I've gotten the basic drag-and-drop functionality taken care of, and I'm able to add a single item to my page, but I'm hitting a snag.
When I drag a new item to my drop zone, the expected behavior is that it will add a new item to the existing array that I've got stored in a nested object in state but, instead when I drag-and-drop another item to it it is overwriting the previous item, only allowing my to have a single item in my page. I have been beating my head against the wall all day. Below is my code; please comment if you need more and I will do my best to clarify.
So, here is my useState
. I have a couple other items in here, but they're unimportant. All that matters is the content
array:
const [lessonContent, setLessonContent] = useState({
title: '',
courseType: '',
content: [],
});
My function to add an element to lessonContent.content
which is passed to the useDrop
hook:
const handleAddLessonElement = (element: Record<string, unknown>) => {
setLessonContent({
...lessonContent,
content: [...lessonContent.content, element],
});
};
const [{ isOver }, drop] = useDrop(() => ({
accept: 'card',
drop: (item) => handleAddLessonElement(item),
collect: (monitor) => ({
isOver: !!monitor.isOver(),
}),
}));
The useDrag
hook:
const [{ isDragging }, drag] = useDrag(() => ({
type: 'card',
item: {
type: element.value,
value: '',
config: { label: element.label },
},
collect: (monitor) => ({
isDragging: !!monitor.isDragging(),
}),
}));
Also, I'm using the <DNDProvider>
with HTML5Backend
, and I've got it wrapping all components that are utilizing tools from react-dnd
. As I said the basics are working, but I seem to be messing something up in adding to state. I just cannot, for the life of me, find what it is.
Thanks in advance!
Ended up figuring out, turns out it was a solution I had tried but hadn't implemented correctly.
My problem is that I was not tracking the array as it updated, so I was constantly overwriting what I had just done. So, all it took was updating my handleAddLessonElement
function to track the updated state before adding an element to the array.
const handleAddLessonElement = (element: Record<string, unknown>) => {
setLessonContent((previousState: Record<string, any>) => ({
...previousState,
content: [...previousState.content, element],
}));
};
As you can see, I added the previousState
which will track the newly update state as I add elements, then use the spread operator to add these new elements to the copied array.