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();
...
}
}
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.
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:
Then you can access the node just like we used to do with our old friends
findDOMNode()
orgetDOMNode()
: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 thecomponent.node
as expected:Here it is in action:
https://jsfiddle.net/h4w4btz9/2/
React-DnD
's API is super flexible—we can (ab)use this.For example, React-DnD lets us determine what connectors are passed to the underlying component. Which means we can wrap them, too. :)
For example, let's override the target connector to store the node on the monitor. We will use a
Symbol
so we do not leak this little hack to the outside world.Now in your
hover
method, you can useThis approach piggybacks on React-DnD's flow and shields the outside world by using a
Symbol
.Whether you're using this approach or the class-based
this.node = node
ref approach, you're relying on the underlying React node. I prefer this one because the consumer does not have to remember to manually use aref
other than the ones already required by React-DnD, and the consumer does not have to be a class component either.Better Solution
A better solution is to just wrap your draggable component with a
div
, define a ref on that and pass it to the draggable component, i.e.and
MyComponent
is wrapped inDragSource
. Now you can just use(
props.node &&
is just added to avoid to callgetBoundingClientRect
on an undefined object)Alternative for
findDOMNode
If you don't want to add a wrapping
div
, you could do the following. The reply of @imjared and the suggested solution here don't work (at least inreact-dnd@2.3.0
andreact@15.3.1
).The only working alternative for
findDOMNode(component).getBoundingClientRect();
which does not usefindDOMNode
is:which is not very beautiful and dangerous because
react
could change this internal path in future versions!Other (weaker) Alternative
Use
monitor.getDifferenceFromInitialOffset();
which will not give you precise values, but is perhaps good enough in case you have a small dragSource. Then the returned value is pretty predictable with a small error margin depending on the size of your dragSource.