【问题标题】:How to implement react-dnd useDragLayer?如何实现 react-dnd useDragLayer?
【发布时间】:2021-11-25 03:08:49
【问题描述】:

我有一个组件当前使用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> 
)

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

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

【问题讨论】:

    标签: reactjs drag-and-drop react-dnd


    【解决方案1】:

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

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

    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 });
    }, []);
    
    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",
      };
    }
    
    
    1. &lt;CustomDragLayer /&gt; 添加到顶级组件

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

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-16
      • 1970-01-01
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 2023-01-16
      • 2018-07-26
      • 2013-01-25
      相关资源
      最近更新 更多