When I drag and drop a Component into my Box and then try to drag and drop the element in another Box, that looks the same from the code. I get an error. How could I fix that? It should be possible to drag and drop the component in every box.
Here the Error:
ERROR Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of
Box
. Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Here the code:
import { FC, useState, createElement, memo } from 'react';
import { useDrop, useDrag, DragSourceMonitor } from 'react-dnd';
import { ItemTypes } from '../constants/ItemTypes';
const Box: FC<any> = ({ prop }) => {
const [item, setItem] = useState<any>();
const [, drop] = useDrop<any>(() => ({
accept: ItemTypes.BOX,
drop(itemDrag, monitor) {
console.log(typeof(itemDrag));
console.log(itemDrag)
setItem(itemDrag);
},
collect: monitor => ({
isOver: !!monitor.isOver(),
}),
}));
const [{ isDragging }, drag] = useDrag(() => ({
type: ItemTypes.BOX,
item: { item: item },
canDrag: item,
collect: (monitor: DragSourceMonitor) => ({
isDragging: !!monitor.isDragging(),
})
}));
return (
<div ref={drop} style={{ backgroundColor: "#FF0000" }}>
{prop}
{item && (
<div ref={drag}>
{createElement(item.item)}
</div>
)}
</div>
);
};
export default memo(Box);
I found out, that the React Component becomes undefined while the second drop:
console.log in the drop function of useDrop hook:
First drop from Container:
Objectitem: () => {…}[[Prototype]]: Object
Second drop from Box:
Objectitem: undefined[[Prototype]]: Object
I found additional out, that if I use the useDrag within the component it self the issue is not there, only if I use my DragWrapper Component. But I want to use it, it will spare me copy and paste and will make it easer to change (but you know all that :-)) Additional here the code from the DragWrapper component:
import { ComponentType, FC, ReactNode, createElement } from 'react';
import { useDrag, DragSourceMonitor } from 'react-dnd';
import { ItemTypes } from '../constants/ItemTypes';
interface DragWrapperType {
child: ComponentType<any>
props?: Object
}
const DragWrapper: FC<DragWrapperType> = ({ child, props }) => {
const [{ isDragging }, drag] = useDrag(() => ({
type: ItemTypes.BOX,
item: { item: child },
collect: (monitor: DragSourceMonitor) => ({
isDragging: !!monitor.isDragging(),
})
}))
return (
<div ref={drag}>
{child && createElement(child, props)}
</div>
);
};
export default DragWrapper;
So issue solved.
It seems like the Object was undefined, because it was from the beginning undefined. I guess the useDrag hook was at the beginning initialized and never changed throw the useStat hook.
To solve the issue I just had to get sure, the useDrag hook initialize when there is a defined object, I used the DragWrapper for that:
{item && item.item &&(
<DragWrapper child={item.item} />
)}