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

React-beautiful-dnd:如何修复isDraggingOver时列表项下滑问题

react-beautiful-dnd拖拽时列内卡片异常跳动问题

我开发了一个基于react-beautiful-dnd的应用,支持用户在不同列之间拖拽卡片。当将卡片拖入已有卡片的列时,现有卡片会向下跳动。若将卡片拖到列顶部,这种情况合理,但即使拖到列表中间或底部,首项或上方所有卡片仍会下滑。释放鼠标完成拖拽后,卡片会恢复到正确位置,因此问题与isDraggingOver相关。我检查了styled components,发现isDraggingOver仅改变背景色和边框色。

9/6 更新:尝试@Jordan的方案未成功后,我查看项目GitHub Issues找到相关问题。发现不渲染provided.placeholder时问题消失,但控制台会出现未渲染占位符的警告。我尝试用React.cloneElement()包裹它并传入{style: {height: '0'}},但无效。目前只能不渲染占位符,求其他解决办法。

8/25 更新:尝试@Jordan的方案后仍存在问题,以下是我的可拖拽组件TaskCard的代码及对应的Hook代码:

Draggable组件代码

import React, { memo, useState } from 'react'
import { Draggable } from 'react-beautiful-dnd'
import TaskForm from '../TaskForm/TaskForm'
import Task from '../Task/Task'
import { useStyletron } from 'baseui'
import useDraggableInPortal from '../../Hooks/useDraggableInPortal'

const TaskCard = ({ description, id, index, column }) => {
  const renderDraggable = useDraggableInPortal()
  const [isEditing, setIsEditing] = useState(false)
  const [css, theme] = useStyletron()
  const handleEdit = id => {
    setIsEditing(true)
  }
  return (
    <Draggable draggableId={id} index={index}>
      {renderDraggable((provided, snapshot) => (
        <div
          className={css({
            boxSizing: 'border-box',
            ':focus': {
              outline: `${theme.colors.hotPink} 3px solid`,
              borderRadius: '6px',
              margin: '3px',
            }
          })}
          ref={provided.innerRef}
          {...provided.draggableProps}
          {...provided.dragHandleProps}>

          {!isEditing &&
            <Task
              column={column}
              description={description}
              handleEdit={handleEdit}
              id={id}
              snapshot={snapshot}
            />
          }

          {isEditing &&
            <TaskForm
              column={column}
              handleOnCancel={() => setIsEditing(false)}
              initialValues={{ description, id }} isEditing={true}
            />
          }
        </div>
      ))}
    </Draggable>
  )
}

export default memo(TaskCard)

@Jordan提供的Hook代码

import { createPortal } from 'react-dom'
import { useEffect, useRef } from 'react'
const useDraggableInPortal = () => {
  const self = useRef({}).current

  useEffect(() => {
    const div = document.createElement('div')
    div.style.position = 'absolute'
    div.style.pointerEvents = 'none'
    div.style.top = '0'
    div.style.width = '100%'
    div.style.height = '100%'
    self.elt = div
    document.body.appendChild(div)
    return () => {
      document.body.removeChild(div)
    }
  }, [self])

  return (render) => (provided, ...args) => {
    const element = render(provided, ...args)
    if (provided.draggableProps.style.position === 'fixed') {
      return createPortal(element, self.elt)
    }
    return element
  }
}

export default useDraggableInPortal

恳请各位提供有效的修复方案,谢谢!


内容的提问来源于stack exchange,提问作者Neil Girardi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 07:57:12