如何实现react-dnd useDragLayer?

Mic*_*urz 2 drag-and-drop reactjs react-dnd

我有一个组件当前使用useDrag钩子连接到react-dnd。除了预览之外,它运行良好。我想实现useDragLayer来看看它是否能帮助解决我的预览问题,正如许多在线线程所建议的那样。

这是我当前的(简化的)useDrag 实现:

const [{ isDragging }, connectDragSource, connectPreview] = useDrag({
  item,
  collect: monitor => ({
    isDragging: monitor.getItem()?.index === item.index,
  })
})

return (
  <Wrapper ref={connectPreview} isDragging={isDragging}>
    <DragHandle ref={connectDragSource} />
  </Wrapper> 
)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我该如何使用useDragLayer,以有助于我的预览?文档示例对我来说毫无意义......

如何使用useDragLayerapi 连接渲染的组件?useDragLayer不返回拖动源和预览连接器函数(就像useDrag在返回数组的索引 1 和 2 上所做的那样),并且其收集函数也不提供DragSourceConnector实例。那么调用钩子/返回值后我该如何处理呢?

Kha*_*edP 11

我刚刚解决了这个问题并想分享它以帮助其他人:)

您需要做几件事才能使其完全发挥作用。

  1. 通过添加以下 useEffect 禁用默认预览行为
import { getEmptyImage } from "react-dnd-html5-backend";

const [{ isDragging }, drag, dragPreview] = useDrag(() => ({
  type: "BOX",
  collect: (monitor) => ({
    isDragging: monitor.isDragging(),
  }),
}));

useEffect(() => {
  dragPreview(getEmptyImage(), { captureDraggingState: true });
}, []);
Run Code Online (Sandbox Code Playgroud)
  1. 创建自定义默认图层

export const CustomDragLayer = (props: {}) => {
  const {
    itemType,
    isDragging,
    initialCursorOffset,
    initialFileOffset,
    currentFileOffset,
  } = useDragLayer((monitor) => ({
    item: monitor.getItem(),
    itemType: monitor.getItemType(),
    initialCursorOffset: monitor.getInitialClientOffset(),
    initialFileOffset: monitor.getInitialSourceClientOffset(),
    currentFileOffset: monitor.getSourceClientOffset(),
    isDragging: monitor.isDragging(),
  }));

  if (!isDragging) {
    return null;
  }

  return (
    <div style={layerStyles}>
      <div
        style={getItemStyles(
          initialCursorOffset,
          initialFileOffset,
          currentFileOffset
        )}
      >
        <div>Your custom drag preview component logic here</div>
      </div>
    </div>
  );
};

const layerStyles: CSSProperties = {
  position: "fixed",
  pointerEvents: "none",
  zIndex: 100,
  left: 0,
  top: 0,
  width: "100%",
  height: "100%",
  border: "10px solid red",
};

function getItemStyles(
  initialCursorOffset: XYCoord | null,
  initialOffset: XYCoord | null,
  currentOffset: XYCoord | null
) {
  if (!initialOffset || !currentOffset || !initialCursorOffset) {
    return {
      display: "none",
    };
  }

  const x = initialCursorOffset?.x + (currentOffset.x - initialOffset.x);
  const y = initialCursorOffset?.y + (currentOffset.y - initialOffset.y);
  const transform = `translate(${x}px, ${y}px)`;

  return {
    transform,
    WebkitTransform: transform,
    background: "red",
    width: "200px",
  };
}

Run Code Online (Sandbox Code Playgroud)
  1. 添加<CustomDragLayer />到顶级组件

您需要将 包含到ref={drag}要拖动的组件中并connectPreview完全删除引用。

希望这对您有帮助。