react-dnd的另一种用法

391 阅读1分钟

react-dnd的基本用法:

import { useDrop } from 'react-dnd'

function myDropTarget(props) {
  const [collectedProps, drop] = useDrop(() => ({
    accept
  }))

  return <div ref={drop}>Drop Target</div>
}

有一种情况你用的组件是函数组件或者是class组件,由于写组件的人没有把ref透传到最外层的dom上,这时如果直接<Component ref={drop} /> 这么子使用会报错Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?,也许你会包多一层div在最外层如:<div ref={drop}><Component /></div> 这样也是可以的,但是如果你不想包一层div也是可以的,只要满足drop({current: HTMLElement}) 这样的形式,react-dnd也是可以接管到的。

所以我们可以自己封装一个高级组件HOC 通过调用ReactDOM.findDOMNode 去获取类组件或者是class组件最外层的dom元素 ,把drop方法当初props传给高级组件HOC如:

const DropComponent = ({ children, id }) => {
  const [{ isOverCurrent, isOver }, drop] = useDrop(() => ({
    accept: ItemTypes.BOX,
    drop: (item, monitor) => {},
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      isOverCurrent: monitor.isOver({ shallow: true }),
    }),
  }));

  return <DomWrapper dropRef={drop}>
    {children}
  </DomWrapper>
  ;
};

// 包一层防止react-dnd获取不到dom实例
class DomWrapper extends React.PureComponent {
  componentDidMount() {
    this.props.dropRef({current: ReactDOM.findDOMNode(this)});
  }
  render() {
    return this.props.children;
  }
}