React DnD: Avoid using findDOMNode

joshhunt picture joshhunt · Nov 9, 2016 · Viewed 9.5k times · Source

I don't fully understand it but apparently it isn't recommended to use findDOMNode().

I'm trying to create drag and drop component but I'm not sure how I should access refs from the component variable. This is an example of what I currently have:

const cardTarget = {
    hover(props, monitor, component) {
        ...
        // Determine rectangle on screen
        const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();
        ...
    }
}

Source

Edit

It might be caused by my component being both the drag and drop source and target as I can get it to work in this example but not this one.

Answer

imjared picture imjared · Nov 14, 2016

Assuming you're using es6 class syntax and the most recent version of React (15, at time of writing), you can attach a callback ref like Dan did in his example on the link you shared. From the docs:

When the ref attribute is used on an HTML element, the ref callback receives the underlying DOM element as its argument. For example, this code uses the ref callback to store a reference to a DOM node:

<h3
    className="widget"
    onMouseOver={ this.handleHover.bind( this ) }
    ref={node => this.node = node}
>

Then you can access the node just like we used to do with our old friends findDOMNode() or getDOMNode():

handleHover() {
  const rect = this.node.getBoundingClientRect(); // Your DOM node
  this.setState({ rect });
}

In action: https://jsfiddle.net/ftub8ro6/

Edit:

Because React DND does a bit of magic behind the scenes, we have to use their API to get at the decorated component. They provide getDecoratedComponentInstance() so you can get at the underlying component. Once you use that, you can get the component.node as expected:

hover(props, monitor, component) {
    const dragIndex = monitor.getItem().index;
    const hoverIndex = props.index;
    const rawComponent = component.getDecoratedComponentInstance();
    console.log( rawComponent.node.getBoundingClientRect() );
    ...

Here it is in action:

https://jsfiddle.net/h4w4btz9/2/