Hey,
I've just switched to Preact and I've found some inconsistencies with the way the ref callback works. I have a draggable (DragSource) item from React DnD that I need the ref for, in order to use it for other purposes in my app. The below code gives me the ref in React, but the same does not happen in Preact (with Preact compat). The setRef function is simply never called in Preact. Any idea what might be happening here and how to work around it?
If I try to get the ref of the image, that works, so as a workaround I could add another div inside and get the ref there, but I don't want to add unnecessary containers. So a proper solution for this would be nice.
class MyComponent extends PureComponent {
//...
setRef = (ref) => {
this.DOMNode = ref;
}
render () {
const { connectDragSource, isDragging, item } = this.props;
return connectDragSource(
<div ref={this.setRef}>
<img src={item.src} alt={item.name} />
</div>
)
}
}
This is because ReactDnD higher component wraps lower component's ref in its own in here, and extract original ref in here. Preact's vnode doesn't have ref property on itself, but in attributes. You can use Preact options vnode hook to modify vnode to suit this your usecase.
import { options } from 'preact'
options.vnode = function (vnode) {
if (vnode.attributes && vnode.attributes.ref) {
vnode.ref = vnode.attributes.ref
}
return vnode
}
This should fix your issue.
Yup! Here's another solution similar to @yaodingyd's lovely answer that patches all VNodes through their prototype:
import { h } from 'preact';
const VNode = h('a').constructor
Object.defineProperty(VNode.prototype, 'ref', {
get() { return this.attributes.ref },
set(v) { this.attributes.ref = v }
});
Sorry, I cannot get any of those fixes to work. Here is a codepen https://codepen.io/cattermo/pen/zYxyGEw
If any of you just have a minute to see whats wrong. Maybe the suggested solutions does not work with preact/compat?
@cattermo you could do something like this in modern preact: https://codesandbox.io/s/cranky-tesla-1xz24
Most helpful comment
@cattermo you could do something like this in modern preact: https://codesandbox.io/s/cranky-tesla-1xz24