To start, for this project I use react-beautiful-dnd
, Chakra UI, and Next.js. This is the link to the video that displays the problem: https://youtu.be/8maSmqahjfw. I've tried doing ondragupdate
, ondragstart
, and ondragend
, various reordering and it still didn't fully work. I wonder if it is because I am also using Chakra UI or that my flex chakra item is just very large with lots of content. This is my code for the draggable, where I loop and add the links:
setLinks((prevRows) => [
...prevRows,
<Draggable
key={element.order}
draggableId={`draggable-${element.order}`}
index={element.order}
>
{(provided, snapshot) => (
<Flex
direction={"column"}
padding={3}
justifyContent={"center"}
alignItems={"center"}
width={{ base: "95%", md: "70%", lg: "70%" }}
backgroundColor={"#fff"}
boxShadow={"0px 0px 3px 0px #b0b0b0"}
borderRadius={10}
// ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
//opacity={snapshot.isDragging ? 0.5 : 1}
>
<Flex
width={"100%"}
justifyContent={"space-between"}
alignItems={"center"}
>
<Flex
alignItems={"center"}
justifyContent={"center"}
gap={1}
>
<Button
colorScheme="transparent"
_hover={{
cursor: "grab",
//backgroundColor: "#efefef",
}}
_active={{
cursor: "grabbing",
}}
>
<DragHandleIcon color={"black"} />
</Button>
<Flex
position="relative"
w={{
base: "100px",
md: "120px",
lg: "140px",
}}
h={{ base: "60px", md: "80px", lg: "100px" }}
bg="transparent"
borderRadius="none"
alignItems={"center"}
justifyContent={"center"}
overflow="hidden"
border={"1px dashed black"}
>
{/* {"Url " + console.log(urls[i])} */}
{urls[i] != null ? (
<>
<Image
src={urls[i]}
alt="Selected Image"
objectFit="cover"
w="100%"
h="100%"
/>
</>
) : (
<Box
//p={6}
textAlign="center"
backgroundColor={"none"}
>
<Text fontSize={"10pt"} fontWeight={700}>
No Image
</Text>
</Box>
)}
</Flex>
<Flex
direction={"column"}
alignItems={"flex-start"}
justifyContent={"center"}
width={"100%"}
>
<Input
value={element.title}
border={"none"}
fontSize={"12pt"}
//maxWidth={"100%"}
//isReadOnly={!selectedInput || selectedInput !== input}
isReadOnly={true}
//onFocus={() => setSelectedOrder(i)}
/>
<Input
isReadOnly={true}
type={"url"}
border={"none"}
fontSize={"9pt"}
value={element.url}
//maxWidth={"100%"}
/>
</Flex>
</Flex>
<Flex
direction={"column"}
alignItems={"center"}
justifyContent={"center"}
gap={5}
>
<Switch
defaultChecked={element.active}
value={element.order}
onChange={handleCheckboxChange}
/>
<Menu>
<MenuButton as={Button} colorScheme="transparent">
<Image
src="/triple.png"
alt={"triple dots"}
width={22}
height={22}
/>
</MenuButton>
<MenuList>
<MenuItem onClick={() => takeCharge(element.order)}>
Edit
</MenuItem>
<MenuItem
onClick={() => {
setDeleteIn(element.order);
onOpen4();
}}
>
Delete
</MenuItem>
</MenuList>
</Menu>
</Flex>
</Flex>
</Flex>
)}
</Draggable>,
]);
And this is the code for the dragdropcontext
and droppable
, I have been also getting some troubles with the provided placeholder as the flex items sometimes stick to each other as shown in the video when I try to drag the other item:
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<Flex
direction={"column"}
alignItems={"center"}
ref={provided.innerRef}
{...provided.droppableProps}
width={"100%"}
height={"100%"}
gap={8}
>
{links}
{provided.placeholder}
</Flex>
)}
</Droppable>
</DragDropContext>
Finally, this is my ondragend
function that I use to reorder all of my elements after drag finished:
const onDragEnd = (result) => {
if (!result.destination) {
return;
}
const newItems = Array.from(links);
const [reorderedItem] = newItems.splice(result.source.index, 1);
newItems.splice(result.destination.index, 0, reorderedItem);
setLinks(newItems);
};