React-dnd: Hooks API ν† λ‘ 

에 λ§Œλ“  2018λ…„ 10μ›” 26일  Β·  43μ½”λ©˜νŠΈ  Β·  좜처: react-dnd/react-dnd

λˆ„κ΅°κ°€ κ²°κ΅­ λ¬Όμ–΄ 보렀고 ν–ˆμ–΄μš”! μƒˆλ‘œμš΄ 후크 APIκ°€ 여기에 도움이 될 수 μžˆμŠ΅λ‹ˆλ‹€. λŒ€λΆ€λΆ„μ˜ APIλŠ” HOCλ₯Ό 후크에 직접 λ§€ν•‘ν•˜μ—¬ 거의 λ™μΌν•˜κ²Œ μœ μ§€ν•  수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

connectDragSource 및 connectDropTarget 을 useRef 값을 μ „λ‹¬ν•˜λŠ” κ²ƒμœΌλ‘œ λŒ€μ²΄ ν•  수 μžˆλŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€. κ°€λŠ₯ν•˜λ‹€λ©΄ ν™•μ‹€νžˆ 물건을 κΉ¨λ—ν•˜κ²Œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€!

design decisions discussion

λͺ¨λ“  43 λŒ“κΈ€

이 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ 후크 μ‚¬μš©μ„ μ‹œμž‘ν•˜κΈ°λ₯Ό 기닀릴 수 μ—†μŠ΅λ‹ˆλ‹€. μœ ν˜•μ΄ μ•ŒνŒŒμ— λŒ€ν•΄ 베이킹 되 자마자 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ λΆ„κΈ°λ₯Ό μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ”μ΄ APIκ°€ μ–΄λ–»κ²Œ 보일지 μƒκ°ν•˜κΈ° μœ„ν•΄ μ‹€ν—˜ / ν›„ν¬μ˜ λΈŒλžœμΉ˜μ—μ„œ 놀고 μžˆμŠ΅λ‹ˆλ‹€. BoardSquare ꡬ성 μš”μ†ŒλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

const dropTarget = createDropTarget(ItemTypes.KNIGHT, {
    canDrop: (props: BoardSquareProps) => canMoveKnight(props.x, props.y),
    drop: (props: BoardSquareProps) => moveKnight(props.x, props.y),
})

const BoardSquare = ({ x, y, children }) => {
    const black = (x + y) % 2 === 1
    const [connectDropTarget, isOver, canDrop] = useDnd(
        dropTarget,
        connect => connect.dropTarget,
        (connect, monitor) => !!monitor.isOver,
        (connect, monitor) => !!monitor.canDrop,
    )

    return connectDropTarget(
        <div>
            <Square black={black}>{children}</Square>
            {isOver && !canDrop && <Overlay color={'red'} />}
            {!isOver && canDrop && <Overlay color={'yellow'} />}
            {isOver && canDrop && <Overlay color={'green'} />}
        </div>,
    )
}

κ·Έλž˜μ„œ μ—¬κΈ°μ„œ μ•„μ΄λ””μ–΄λŠ” createDropTarget κ°€ λ“œλž˜κ·Έ / λ“œλ‘­ ν•­λͺ©μ— λŒ€ν•œ 논리적 지식, ID 및 μ˜ˆμΈ‘μ„ μ„€μ •ν•˜κ³  useDnd 후크가이λ₯Ό DnD μ‹œμŠ€ν…œμ— μ—°κ²°ν•˜κ³  μ†Œν’ˆμ„ μˆ˜μ§‘ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

이것은 단지 후보 λ””μžμΈμ„ μŠ€μΌ€μΉ˜ ν•œ κ²ƒμž…λ‹ˆλ‹€. μ‹€μ œλ‘œ κ΅¬ν˜„λ˜μ§€λŠ” μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

@darthtrevino μ–΄λ–€ μ§€μ μ—μ„œ μž‘μ—…ν•˜κ³  μžˆμŠ΅λ‹ˆκΉŒ? refsλ₯Ό μ‚¬μš©ν•˜μ—¬ connectDropTarget λͺ¨λ‘ 제거 ν•  수 μžˆλŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€. λ‚˜λŠ” λ‹Ήμ‹ μ˜ μ§€μ μ—μ„œ μž‘λ™ν•˜λ„λ‘ ν•  수 μžˆλŠ”μ§€λ³΄κ³  μ‹ΆμŠ΅λ‹ˆλ‹€!

const dropTarget = createDropTarget(ItemTypes.KNIGHT, {
    canDrop: (props: BoardSquareProps) => canMoveKnight(props.x, props.y),
    drop: (props: BoardSquareProps) => moveKnight(props.x, props.y),
})

const BoardSquare = ({ x, y, children }) => {
    const dropTargetElement = useRef(null);
    const black = (x + y) % 2 === 1
    const [isOver, canDrop] = useDnd(
        dropTargetElement,
        dropTarget,
        ...
    )

    return (
        <div ref={dropTargetElement}>
            <Square black={black}>{children}</Square>
            {isOver && !canDrop && <Overlay color={'red'} />}
            {!isOver && canDrop && <Overlay color={'yellow'} />}
            {isOver && canDrop && <Overlay color={'green'} />}
        </div>
    )
}

@ jacobp100 μ°Έμ‘°κ°€ 제곡되고 후크 μžμ²΄μ—μ„œ λ°˜ν™˜λ˜λŠ” μœ μ‚¬ν•œ 후크 기반 API (예 const [isOver, canDrop, ref] = useDnd(...) ), μ†ŒλΉ„ ꡬ성 μš”μ†Œκ°€ JSX νŠΈλ¦¬μ— 배치 ν•  μ€€λΉ„κ°€ 된 것 κ°™μŠ΅λ‹ˆλ‹€.)

그게 νš¨κ³Όκ°€ μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μ—¬λŸ¬ ν›„ν¬μ—μ„œ refλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 μ–΄λ ΅μ§€λ§Œ μ—¬λŸ¬ refλ₯Ό 단일 ref둜 κ²°ν•©ν•˜λŠ” 무언가λ₯Ό μž‘μ„±ν•˜λŠ” 것을 막을 μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€. 이것은 μ–΄λ–€ λ„μ„œκ΄€ μ΄μ—ˆμŠ΅λ‹ˆκΉŒ?

이것에 λŒ€ν•œ μ»¨λ²€μ…˜μ΄ 무엇인지 봐야 ν•  것 κ°™μ•„μš”!

μ—¬λŸ¬ ν›„ν¬μ—μ„œ refλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 μ–΄λ ΅μ§€λ§Œ μ—¬λŸ¬ refλ₯Ό 단일 ref둜 κ²°ν•©ν•˜λŠ” 것을 μž‘μ„±ν•˜λŠ” 것을 막을 μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€.

μ°Έ, μ°Έ :-)

이것은 μ–΄λ–€ λ„μ„œκ΄€ μ΄μ—ˆμŠ΅λ‹ˆκΉŒ?

λ‹€μ‹œ 찾을 μˆ˜μ—†λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€ atm :-/-μ§€λ‚œ 2 μ£Ό λ™μ•ˆ 후크에 λŒ€ν•œ λ§Žμ€ μ‹€ν—˜ ...

https://github.com/beizhedenglong/react-hooks-lib κ°€ μžˆμŠ΅λ‹ˆλ‹€.
const { hovered, bind } = useHover(); return <div {...bind}>{hovered ? 'yes' : 'no'}</div>;
bind 에 μ‹¬νŒμ΄ ν¬ν•¨λ˜μ–΄ μžˆλ‹€λŠ” λœ»μΈκ°€μš”?
[νŽΈμ§‘ : μ•„λ‹ˆμš”, λ¬Όλ‘  { onMouseEnter, onMouseLeave } 만 ν¬ν•¨ν•©λ‹ˆλ‹€ ...]

ν•˜μ§€λ§Œ λ‹€λ₯Έ APIκ°€ ν›„ν¬μ—μ„œ λ°”λ‘œ μ°Έμ‘°λ₯Ό λ°˜ν™˜ν•˜λŠ” 것을 λ³Έ 기얡이 μžˆμŠ΅λ‹ˆλ‹€.

그닀지 λ§Žμ§€ μ•Šκ³  ν˜„μž¬ 건물이 μ•„λ‹Œλ° μ œκ°€μžˆλŠ” 지점은 experiment/hooks

μ—¬κΈ°μ—μ„œ λ°˜λ³΅ν•©λ‹ˆλ‹€.

const dropTarget = createDropTarget(ItemTypes.KNIGHT, {
    canDrop: props => canMoveKnight(props.x, props.y),
    drop: props => moveKnight(props.x, props.y),
})

const BoardSquare = ({ x, y, children }) => {
    const black = (x + y) % 2 === 1
        const ref = useRef(null)
    const [isOver, canDrop] = useDnd(
        connect => connect(ref, dropTarget),
        monitor => monitor.isOver,
        monitor => monitor.canDrop,
    )

    return (
        <div ref={ref}>
            <Square black={black}>{children}</Square>
            {isOver && !canDrop && <Overlay color={'red'} />}
            {!isOver && canDrop && <Overlay color={'yellow'} />}
            {isOver && canDrop && <Overlay color={'green'} />}
        </div>,
    )
}

이것이 dragSource 및 dropTarget 연결이 μž‘λ™ν•˜λŠ” λ°©μ‹μž…λ‹ˆλ‹€. refλ₯Ό 첫 번째 인수둜 μ‚¬μš©ν•˜λ©΄ λ‚˜λ¨Έμ§€ μΈμˆ˜κ°€ μ—¬λŸ¬ dnd κ°œλ…μ— μ—°κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

const dropTarget = createDropTarget(ItemTypes.CARD, {
    canDrop: () => false
    hover(props, monitor) {
        /**/
    },
})
const dragSource = createDragSource(ItemTypes.CARD, {
    beginDrag: props => /*...*/,
    endDrag: (props, monitor) => /*...*/
})

function Card({ text }) {
    const ref = useRef(null)
    const [isDragging] = useDnd(
        connect => connect(ref, dropTarget, dragSource),
        monitor => monitor.isDragging,
    )
    const opacity = isDragging ? 0 : 1

    return (
        <div ref={ref} style={{ ...style, opacity }}>
            {text}
        </div>
    )
}

λ”°λΌμ„œ useDndλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

export type DndConcept = DragSource | DropTarget
export type ConnectorFunction = (connector: Connector /*new type*/) => void
export type CollectorFunction<T> = (monitor: DragDropMonitor) => T

export function useDnd(
    connector: ConnectorFunction,
    ...collectors: CollectorFunction[]
): any[] {
    const dragDropManager = useDragDropManager()
        // magic
       return collectedProperties
}

export function useDragDropManager(): DragDropManager {
    return useContext(DragDropContextType)
}

connect 및 monitor μ‹ κ²½ 쓰지 μ•Šμ•˜λ‹€λ©΄ μ–΄λ–¨κΉŒμš”?

const Test = props => {
  const ref = useRef(null);
  const { isDragging } = useDragSource(ref, ItemTypes.CARD, {
    canDrag: props.enabled,
    beginDrag: () => ({ id: props.id }),
  });

  return <div ref={ref} style={{ color: isDragging ? 'red' : 'black' }} />
}

연결을 제거 ν•  수 μžˆλ‹€κ³  μƒκ°ν•˜μ§€λ§Œ λͺ¨λ‹ˆν„°μ— λŒ€ν•΄μ„œλŠ” 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. isDragging

κ·Έλž˜μ„œ μ•„λ§ˆλ„ useDragSource(ref, <type>, <spec>, <collect>) . 그것은 λ§Žμ€ λ…ΌμŸμ΄λ©°, 두 개의 λš±λš±ν•œ 물체가 λ‚˜λž€νžˆ λΆ™μ–΄μžˆλŠ” 것이 이상 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έλž˜λ„ λͺ¨λ‹ˆν„°μ—μ„œ λͺ¨λ“  μ†Œν’ˆμ„ λ°˜ν™˜ ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

μ–΄μ©Œλ©΄,이 λ¬Έμ œκ°€ 원인이 μœ μΌν•œ 방법이라고 생각 : https://github.com/react-dnd/react-dnd/blob/84db06edcb94ab3dbb37e8fe89fcad55b1ad07ce/packages/react-dnd/src/interfaces.ts#L117

IIRC, DragSourceMonitor, DropTragetMonitor 및 DragLayerMonitorλŠ” λͺ¨λ‘ DragDropMonitor ν΄λž˜μŠ€μ— μ†ν•©λ‹ˆλ‹€. κ·Έλž˜μ„œ λ‚˜λŠ” μš°λ¦¬κ°€ 이름 μΆ©λŒμ— λΆ€λ”ͺ 힐 것이라고 μƒκ°ν•˜μ§€ μ•Šμ§€λ§Œ λ‚˜λŠ” 그것을 λ‹€μ‹œ ν™•μΈν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

@yched κ·Έλƒ₯ 이것과 훅을 가지고 놀닀가 μš°λ¦¬κ°€ μ°Έμ‘°λ₯Ό μ „λ‹¬ν•΄μ•Όν•œλ‹€λŠ” 것을 μ•Œμ•„ μ±˜μŠ΅λ‹ˆλ‹€. 무언가가 μ†ŒμŠ€μ™€ νƒ€κ²Ÿ λͺ¨λ‘ 인 경우λ₯Όλ³΄μ‹­μ‹œμ˜€.

const Test = () => {
  const ref = useRef(null)
  const source = useDragSource(ref, …props)
  const target = useDragTarget(ref, …props)

  return <div ref={ref}>…</div>
}

@ jacobp100 μ‹€μ œλ‘œ μ˜λ―Έκ°€ μžˆμŠ΅λ‹ˆλ‹€.

μ’‹μ•„μš”, 아이디어

const Test = (props) => {
  const ref = useRef(null)
  const sourceMonitor = useDragSource(ref, 'item' {
    beginDrag: () => ({ id: props.id })
  })
  const targetMonitor = useDropTarget(ref, ['item'] {
    drop: () => alert(targetMonitor.getItem().id)
  })
  const { isDragging } = useMonitorSubscription(targetMonitor, () => ({
    isDragging: targetMonitor.isDragging()
  })

  return <div ref={ref}>…</div>
}

λ“œλž˜κ·Έ μ†ŒμŠ€ 및 λŒ€μƒμ— λŒ€ν•œ 사양은 이미 μ•‘μ„ΈμŠ€ κΆŒν•œμ΄ μžˆμœΌλ―€λ‘œ 맀개 λ³€μˆ˜λ₯Ό μˆ˜μ‹ ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

useMonitorSubscription λŠ” 객체에 λŒ€ν•΄ 얕은 동등을 μˆ˜ν–‰ν•˜μ—¬ μ—…λ°μ΄νŠΈλ₯Ό 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” μ—¬κΈ°λ₯Ό 처음 μ‚΄νŽ΄ λ³΄μ•˜λ‹€. ν…ŒμŠ€νŠΈλŠ” μ—†μ§€λ§Œ 체슀 μ˜ˆμ œλŠ” 후크와 ν•¨κ»˜ μž‘λ™ν•©λ‹ˆλ‹€. λ‚΄κ°€ μ›ν•˜λŠ” 것을 보여쀄 κ²ƒμž…λ‹ˆλ‹€!

λ‚˜λŠ” useDragSource(ref, <type>, <spec>, <collect>) λ₯Ό κ°–λŠ” 것이 정말 ν›Œλ₯­ν•˜κ²Œ μž‘λ™ν•˜κ³  λ§Žμ€ API 변경을 κ°€μ Έ μ˜€μ§€ μ•ŠλŠ” μ œμ•ˆμ΄λΌκ³  μƒκ°ν•©λ‹ˆλ‹€. μœ μΌν•œ 차이점은 hocμ—μ„œ hook으둜 λ³€κ²½ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

λ˜ν•œ 두 개의 λš±λš±ν•œ 물체λ₯Ό λ‚˜λž€νžˆ λ‘λŠ” 것은 이전에도 κ·Έλ ‡κ²Œν•΄μ•Όν–ˆκΈ° λ•Œλ¬Έμ— λ‚΄ μƒκ°μ—λŠ” 큰 λ¬Έμ œκ°€ μ•„λ‹™λ‹ˆλ‹€.

const DragDrop = () => {
  const ref = useRef(null);

  const dragSource = {
    beginDrag() {
      return props;
    }
  };

  const collectSource = monitor => {
    return {
      isDragging: monitor.isDragging()
    };
  };

  const { isDragging } = useDragSource(ref, "Item", dragSource, collectSource);

  const dropTarget = {
    drop() {
      return undefined;
    }
  };

  const collectTarget = monitor => {
    return {
      isOver: monitor.isOver()
    };
  };

  const { isOver } = useDropTarget(ref, "Item", dropTarget, collectTarget);

  return <div ref={ref}>Drag me</div>;
};

쒋은 점은 λ‹€λ₯Έ ν›„ν¬μ˜ 값도 μ‚¬μš©ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

const Drag = () => {
  const ref = useRef(null);
  const context = useContext(Context)

  const dragSource = {
    beginDrag() {
      context.setDragItem(props)
      return props;
    },
    endDrag() {
      context.setDragItem(null)
    }
  };

  const collectSource = monitor => {
    return {
      isDragging: monitor.isDragging()
    };
  };

  const { isDragging } = useDragSource(ref, "Item", dragSource, collectSource);

  return <div ref={ref}>Drag me</div>;
};

쒋은 μž₯점 쀑 ν•˜λ‚˜λŠ” beginDrag μΈμˆ˜μ—μ„œ props와 ꡬ성 μš”μ†Œλ₯Ό 제거 ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. 그리고 λ‹€λ₯Έ λͺ¨λ“  ν•¨μˆ˜λŠ” 이미 λ²”μœ„μ—μ„œ μ•‘μ„ΈμŠ€ ν•  수 μžˆμœΌλ―€λ‘œ μˆ˜λ½ν•©λ‹ˆλ‹€.

^ 방금 λ§ˆμ§€λ§‰ λŒ“κΈ€μ„ μ—…λ°μ΄νŠΈν•˜μ—¬ collectSource κ°€ λͺ¨λ‹ˆν„°μ—μ„œ ν•¨μˆ˜λ‘œ μ „λ‹¬λ˜μ§€ μ•ŠμŒμ„ λ³΄μ—¬μ£Όμ—ˆμŠ΅λ‹ˆλ‹€. 방금 μŠ€μ½”ν”„μ—μ„œ μ½μ—ˆμŠ΅λ‹ˆλ‹€.

@ jacobp100 μ•Œκ² μŠ΅λ‹ˆλ‹€ . λ‚˜μ—κ²Œ μ§ˆλ¬Έμ€ λͺ¨λ‹ˆν„°μ—μ„œ 데이터λ₯Ό μˆ˜μ§‘ν•˜κΈ° μœ„ν•΄ λ‹€λ₯Έ 후크가 ν•„μš”ν•œμ§€ μ•„λ‹ˆλ©΄ useDragSource 및 useDropTargetμ—μ„œλ„ κ΅¬ν˜„ν•  수 μžˆλŠ”μ§€ μ—¬λΆ€μž…λ‹ˆλ‹€.

물건이 HOC μ˜€μ„ λ•Œ, μ–΄μ¨Œλ“  μ—°κ²° 물건을 μ—°κ²°ν•΄μ•Όν•˜λŠ” 곳은 μ˜λ―Έκ°€μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ΄μ œλŠ” 더 이상 이듀을 μ—°κ²°ν•˜κΈ°μœ„ν•œ 기술적 μš”κ΅¬ 사항이 μ—†μœΌλ―€λ‘œ λ³„λ„λ‘œ λ‘μ—ˆμŠ΅λ‹ˆλ‹€.

그러면 더 자유둭게 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜λ‚˜ μ΄μƒμ˜ ν•˜μœ„ ꡬ성 μš”μ†Œκ°€ λͺ¨λ‹ˆν„° λ³€κ²½ 사항에 응닡 ν•  수 μžˆμ§€λ§Œ 끌기 μ‹œμž‘λœ ꡬ성 μš”μ†ŒλŠ” μ•„λ‹™λ‹ˆλ‹€. λ˜ν•œ λͺ¨λ‹ˆν„° ꡬ독을 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 경우 ν•΄λ‹Ή 후크가 트리 흔듀릴 수 μžˆλ‹€λŠ” μΆ”κ°€ λ³΄λ„ˆμŠ€κ°€ μžˆμŠ΅λ‹ˆλ‹€.

즉, 이것은 초기 μ΄ˆμ•ˆμž…λ‹ˆλ‹€! 그것이 ν•©μ˜λΌλ©΄ λ‚˜λŠ” 그것을 λ³€κ²½ν•˜λŠ” 것에 λ°˜λŒ€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€!

쒋은 μ£Όμž₯μž…λ‹ˆλ‹€. λ‚΄κ°€ λ³΄λŠ” μœ μΌν•œ λ¬Έμ œλŠ” μ‚¬μš©μžκ°€ λͺ¨λ‹ˆν„°λ₯Ό 직접 호좜 ν•  λ•Œ ν˜Όλž€μŠ€λŸ¬μ›Œν•˜κ³  μ™œ μ œλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠλŠ”μ§€ κΆκΈˆν•΄ ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

const Test = (props) => {
  const ref = useRef(null)

  const sourceMonitor = useDragSource(ref, 'item', {
    beginDrag: () => ({ id: props.id })
  })

  const targetMonitor = useDropTarget(ref, ['item'], {
    drop: () => alert(targetMonitor.getItem().id)
  })

  const { isDragging } = useMonitor(targetMonitor, () => ({
    isDragging: targetMonitor.isDragging()
  })

  return <div ref={ref}>{sourceMonitor.isDragging() ? 'Dragging' : 'Drag me'}</div>
}

μ•„λ§ˆλ„ useMonitor 후크 μ™ΈλΆ€μ—μ„œ ν•¨μˆ˜λ₯Ό 호좜 ν•  λ•Œ λ¬Έμ„œ 및 경고둜 ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ‹€μ œλ‘œ μž‘λ™ν•©λ‹ˆλ‹€! 100 % κ΄€μ‹¬μ΄μ—†λŠ” 것 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€. useMonitor 의 μ½œλ°±μ€ λ³€κ²½ 감지와 λ°˜ν™˜ κ°’ λͺ¨λ‘μ— μ‚¬μš©λ©λ‹ˆλ‹€. React core의 ν˜„μž¬ 후크에 μœ„λ°°λ˜λŠ” κ²ƒμ²˜λŸΌ λŠκ»΄μ§‘λ‹ˆλ‹€.

μ•„λ§ˆλ„ 이와 같은 것이 더 잘 μž‘λ™ ν•  κ²ƒμž…λ‹ˆλ‹€.

const Test = (props) => {
  ...
  useMonitorUpdates(targetMonitor, () => [targetMonitor.isDragging()]);

  return <div ref={ref}>{sourceMonitor.isDragging() ? 'Dragging' : 'Drag me'}</div>
}

이 μ–‘μ‹μœΌλ‘œ 버그λ₯Ό λ„μž…ν•˜λŠ” 것이 훨씬 더 μ‰½μŠ΅λ‹ˆλ‹€.

λ°˜μ‘ 및 내뢀에 λŒ€ν•΄ 100 % ν™•μ‹ ν•˜μ§€λŠ” μ•Šμ§€λ§Œ λͺ¨λ‹ˆν„°κ°€ μ—†κΈ° λ•Œλ¬Έμ— λ§ˆμš°μŠ€κ°€ 움직일 λ•Œλ§ˆλ‹€ ꡬ성 μš”μ†Œλ₯Ό λ Œλ”λ§ ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆκΉŒ?

λ”°λΌμ„œ useMonitorSubscription을 μ œκ±°ν•˜κ³  render ν•¨μˆ˜μ— monitor.isDragging() 만 있으면 이전 μž‘μ—…μ΄ μ€‘μ§€λ©λ‹ˆκΉŒ?

λ”°λΌμ„œ μ˜¬λ°”λ₯΄κ²Œ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ?

const Test = (props) => {
  const ref = useRef(null)

  const sourceMonitor = useDragSource(ref, 'item', {
    beginDrag: () => ({ id: props.id })
  })

  return <div ref={ref}>{sourceMonitor.isDragging() ? 'Dragging' : 'Drag me'}</div>
}

λͺ¨λ‹ˆν„°μ—λŠ” 값이 μ—…λ°μ΄νŠΈ 될 λ•Œλ§ˆλ‹€ λ¦¬μŠ€λ„ˆμ—κ²Œ μ•Œλ¦¬λŠ” subscribe λ©”μ†Œλ“œκ°€ μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ μ»΄ν¬λ„ŒνŠΈκ°€ μ—…λ°μ΄νŠΈμ‹œκΈ°λ₯Ό μ•Œ 수 μžˆλ„λ‘ _something_을 μˆ˜ν–‰ν•΄μ•Όν•©λ‹ˆλ‹€.

이전 κ²Œμ‹œλ¬Όμ—μ„œ ν™•μž₯ν•˜μ—¬ λ³€κ²½ 감지 μ΅œμ ν™”λ₯Ό 선택 κΈ°λŠ₯으둜 λ§Œλ“€λ©΄ λ‹€μŒκ³Ό 같이 간단 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

const Test = (props) => {
  ...
  useMonitorUpdates(sourceMonitor);

  return <div ref={ref}>{sourceMonitor.isDragging() ? 'Dragging' : 'Drag me'}</div>
}

λͺ‡ 가지 아이디어.

첫째, 후크가 Ref κ΅¬ν˜„μ„ λ°˜ν™˜ν•˜λ„λ‘ν•˜μ—¬ ref 인수λ₯Ό μ„ νƒμ μœΌλ‘œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆκΉŒ?

const dragSource = useDragSource('item', spec);
return <div ref={dragSource}/>

// or if you want to use a ref
const ref = useRef();
const dragSource = useDragSource('item', dragSourceSpec)(ref); 
const dropTarget = useDropTarget('item', dropTargetSpec)(ref); 

λ‘˜μ§Έ, useMonitorUpdates μ—μ„œ λ‹€λ₯Έ 후크λ₯Ό ν˜ΈμΆœν•˜λ„λ‘ λ§Œλ“œλŠ” λŒ€μ‹  λ‹€μŒμ„ μˆ˜ν–‰ ν•  수 μžˆλŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€.

const dragSource = useDragSource('item', spec);

const { isDragging } = dragSource.subscribe(() => ({
  isDragging: targetMonitor.isDragging()
}));

후보 APIκ°€ μžˆμœΌλ―€λ‘œ μ§€κΈˆμ€μ΄ ν•­λͺ©μ„ λ‹«κ² μŠ΅λ‹ˆλ‹€. μƒˆλ‘œμš΄ λ¬Έμ œμ— λŒ€ν•΄ 자유둭게 μ˜κ²¬μ„ λ§ν•˜μ‹­μ‹œμ˜€. 감사!

후크 API에 λ””μžμΈ κ²°ν•¨μ΄μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€ : https://github.com/Swizec/useDimensions/issues/3

ν₯λ―Έ λ‘­κΈ° λ•Œλ¬Έμ— λŒ€μ•ˆμ€ ν˜„μž¬ 클래슀 기반 APIμ—μ„œν•˜λŠ” κ²ƒμ²˜λŸΌ μ—°κ²° ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

const Box = ({ name }) => {
    const [{ isDragging }, dragSource] = useDrag({
        item: { name, type: ItemTypes.BOX },
        end: (dropResult?: { name: string }) => {
            if (dropResult) {
                alert(`You dropped ${item.name} into ${dropResult.name}!`)
            }
        },
        collect: monitor => ({
            isDragging: monitor.isDragging(),
        }),
    })
    const opacity = isDragging ? 0.4 : 1

    return (
        <div ref={node => dragSource(node)} style={{ ...style, opacity }}>
            {name}
        </div>
    )
}

λ”°λΌμ„œ 일반적으둜 APIλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

const [props, connectDragSource, connectDragPreview] = useDrag(spec)
const [props, connectDropTarget] = useDrop(spec)

컀λ„₯ν„° κΈ°λŠ₯을 μš”κ΅¬ν•˜λŠ” κ²ƒμ—μ„œ λ²—μ–΄λ‚˜κ³  μ‹Άμ—ˆμ§€λ§Œ APIκ°€ μ—†μœΌλ©΄ APIκ°€ μ†μƒλ˜λ©΄ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έλž˜λ„ κ·Έ 문제λ₯Ό μ½μ—ˆμ„ λ•Œ APIλŠ” λΉ„μŠ·ν•˜μ§€λ§Œ DOM λ…Έλ“œλ₯Ό μΈ‘μ •ν•˜κΈ° μœ„ν•΄ λ ˆμ΄μ•„μ›ƒ 효과λ₯Ό μ‚¬μš©ν•˜κ³  μžˆλ‹€λŠ” λ¬Έμ œκ°€ μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” μ‹€μ œλ‘œ λ ˆμ΄μ•„μ›ƒ 효과λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  dnd-core에 DOM λ…Έλ“œλ₯Ό λ“±λ‘ν•©λ‹ˆλ‹€.

@gaearon , μš°λ¦¬κ°€ μ œμ•ˆν•œ 후크 APIλŠ” useDimensions API와 맀우 μœ μ‚¬ν•©λ‹ˆλ‹€. νŠΉμ • ν˜•νƒœκ°€ 반 νŒ¨ν„΄ (예 : let [props, ref] = useCustomHook(config) )μž…λ‹ˆκΉŒ, μ•„λ‹ˆλ©΄ λΌμ΄λΈŒλŸ¬λ¦¬κ°€ ν•΄κ²°ν•˜λ €κ³ ν•˜λŠ” λ¬Έμ œμ™€ νŠΉμ΄ν•œκ°€μš”?

@darthtrevino useDragSource 후크λ₯Ό μ‚¬μš©ν•˜κ³  μ°Έμ‘°λ₯Ό ν•˜μœ„ ꡬ성 μš”μ†Œμ— μ „λ‹¬ν•˜λ©΄ ν•˜μœ„ ꡬ성 μš”μ†Œκ°€ λ‹€μ‹œ λ Œλ”λ§λ˜λŠ” 경우 dnd-core에 등둝 된 dom λ…Έλ“œλ₯Ό μ—…λ°μ΄νŠΈν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

function Parent() {
  const ref = useRef();
  const dragSource = useDragSource(ref, ...);

  return <Child connect={ref} />;
}

function Child({ connect }) {
  const [open, setOpen] = useState(false);

  function toggle() {
    setOpen(!open);
  }

  return (
    <Fragment>
      <button onClick={toggle}>Toggle</button>
      {open ? <div ref={connect} /> : null}
    </Fragment>
  );
}

Yech. 이번 μ£Ό 말에 폭발 μ—¬λΆ€λ₯Ό 증λͺ…ν•˜κΈ° μœ„ν•΄ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό λ§Œλ“€ 수 μžˆλŠ”μ§€ μ‚΄νŽ΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

ν­λ°œν•˜λ©΄ 컀λ„₯ν„° κΈ°λŠ₯을 μ‚¬μš©ν•˜λŠ” 것이 λŒ€μ²΄μž…λ‹ˆλ‹€.

λͺ¨λ“  것을 μ˜¬λ°”λ₯΄κ²Œ μˆ˜ν–‰ν–ˆλ‹€λ©΄ μ—¬κΈ°μ—μ„œ μž¬ν˜„ ν•  μˆ˜μžˆμ—ˆμŠ΅λ‹ˆλ‹€ : https://codesandbox.io/s/xj7k9x4vp4

Kaboom, 쒋은 일, κ°μ‚¬ν•©λ‹ˆλ‹€ @ k15a . 곧 μ—°κ²° ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ„λ‘ 후크 APIλ₯Ό μ—…λ°μ΄νŠΈν•˜κ³  예제λ₯Ό ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ‘œ ν¬ν•¨ν•˜κ² μŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ 어젯밀에 컀λ„₯ν„° ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ 후크 APIλ₯Ό 재 μž‘μ—…ν•˜λŠ” 데 λ§Žμ€ μ‹œκ°„μ„ λ³΄λƒˆμŠ΅λ‹ˆλ‹€. API λ””μžμΈμ— κ΄€ν•œ ν•œ, λ‚˜λŠ” 정말 μ‹«μ–΄ν•©λ‹ˆλ‹€.

λ‚΄ λ‹€μŒ 생각은 ref-object λŒ€μ‹  callback-refλ₯Ό λ°˜ν™˜ ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. 이λ₯Ό 톡해 참쑰둜 직접 μ‚¬μš©ν•˜κ±°λ‚˜ μ°Έμ‘°λ₯Ό 전달할 μˆ˜μžˆλŠ” μœ μ—°μ„±μ„ μ œκ³΅ν•©λ‹ˆλ‹€.

직접 μ‚¬μš© :

let [props, dragSource] = useDrag({spec}) // dragSource result is a function
return <div ref={dragSource} {...props}>hey</div>

체인

let [dragProps, dragSource] = useDrag({spec})
let [dropProps, dropTarget] = useDrag({spec})

return <div ref={node => dragSource(dropTarget(node))}>hey</div>

μ°Έμ‘° 개체 μ‚¬μš©

let ref = useRef(null)
let [dragProps, dragSource] = useDrag({spec})
let [dropProps, dropTarget] = useDrag({spec})
dragSource(dropTarget(ref))

return <div ref={ref}>hey</div>

λ‚˜μ—κ²ŒλŠ” ꡬ성 μš”μ†Œ λ˜λŠ” ν•˜μœ„ μš”μ†Œκ°€ μ—…λ°μ΄νŠΈλ˜λ©΄ useLayoutEffect κ°€ μ‹€ν–‰λ˜μ–΄μ•Όν•˜λŠ” κ²ƒμ²˜λŸΌ λŠκ»΄μ§‘λ‹ˆλ‹€. λ§Œμ•½ κ·Έλ ‡λ‹€λ©΄ μš°λ¦¬λŠ” 그것을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ°˜μ‘ μ €μž₯μ†Œμ— 티켓을 λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€ . μ˜κ²¬μ„ μ£Όμ‹œκΈ° λ°”λžλ‹ˆλ‹€.

let [dragProps, dragSource] = useDrag({spec})
let [dropProps, dropTarget] = useDrag({spec})

return <div ref={node => dragSource(dropTarget(node))}>hey</div>

맀 λ Œλ”λ§λ§ˆλ‹€ refλ₯Ό ν˜ΈμΆœν•˜λŠ” κ²ƒμ²˜λŸΌ 이것이 μ–Όλ§ˆλ‚˜ 잘 μž‘λ™ν•˜λŠ”μ§€ λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ λ Œλ”λ§ ν•  λ•Œλ§ˆλ‹€ μ—°κ²°ν•˜κ³  μ—°κ²° ν•΄μ œν•΄μ•Όν•©λ‹ˆλ‹€.

λ˜ν•œ κ·Έλ ‡κ²Œν•˜λŠ” 것이 낫지 μ•Šμ„κΉŒμš”

node => {
    dragSource(node)
    dropTarget(node)
}

λ˜‘κ°™μ€ 일이야

λ”°λΌμ„œ 이전 μ˜κ²¬μ„ μ‰½κ²Œ μ„€λͺ…ν•˜κΈ° μœ„ν•΄ # 1280의 APIκ°€ 처음 μƒκ°ν–ˆλ˜ 것보닀 더 λ‚˜μ•„μ§ˆ κ²ƒμž…λ‹ˆλ‹€. μ—¬κΈ° λ˜λŠ” 거기에 자유둭게 μ˜κ²¬μ„ λ§ν•˜μ‹­μ‹œμ˜€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰