You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-beautiful-dnd拖拽异常:元素粘连、排序不准确求助

拖拽功能异常问题:元素粘连、排序不准确(基于Next.js + react-beautiful-dnd + Chakra UI)

在基于Next.js、react-beautiful-dnd和Chakra UI的项目中遇到拖拽功能异常:拖拽时元素出现粘连,排序操作不准确。已尝试使用ondragupdate、ondragstart、ondragend事件及多种排序逻辑,但问题仍未完全解决,怀疑可能与Chakra UI的使用或包含大量内容的Flex容器有关。

1. Draggable组件代码(循环添加链接)

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>,
          ]);

2. DragDropContext与Droppable代码

拖拽时Flex元素有时会出现粘连情况:

<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>

3. onDragEnd排序函数

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);
  };

内容的提问来源于stack exchange,提问作者Benjamin Sloutsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 06:32:05