craft.js
craft.js copied to clipboard
useNode - dom is always 1 change behind the actual dom element
Describe the bug
When getting dom from useNode. The dom element from the hook is always 1 iteration behind the actual element on the page.
To Reproduce Set up a useNode hook with dom & style in 1 component
const {
style,
dom,
} = useNode((node) => ({
dom: node.dom,
style: node.data.props.style,
}))
set up a setProp from useNode in a different component. and set the width to 100
The dom.offsetWidth will be 0
if you. then run setProp with style.width set to 200
The dom.offsetWidth will be 100
if you. then run setProp with style.width set to 50
The dom.offsetWidth will be 200
It's always 1 iteration behind the real deal.
This is incredibly frustrating trying to build an outline onRender component. as the size of my outline is always wrong, until a user hovers over the element.
Expected behavior I expect the dom element from useNode to be the actual element and have the same size/position as the element the user sees on the screen.
Screenshots If applicable, add screenshots to help explain your problem.
Initial size on first render is correct (width is set to 600 by default)

using setProp I change the width to 400

Always 1 step behind the actual size :(
When I hover over the element, it fixes itself and corrects back to the right size.
The same problem can be observed in the landing page demo:
If you change the dimensions of something (from the side menu), the position of the "IndicatorDiv" is still at it's old height / position.
Until you hover the element and it updates.
Not sure if it's the same underlying cause, but a similar issue exists when resizing the page - the menu doesn't follow the DOM it's attached to.
See the following as an example:

I am experiencing an issue that is likely related. I have a User Component that maps a prop to render a list of components, i.e.
const MyUserComponent = ({ items }) => {
return (
<div>
{items.map((item) => (
<button>{item}</button>
))}
</div>
);
};
Initially, when the items prop is empty, the indicator shows up properly for my component.
However, when I add an item in the items prop, the dom value returned from useNode now seems to think the dom of my User Component is a <button /> instead of the parent <div />, as shown by the indicator in the screenshot below:
Not knowing the inner mechanics of craftjs, I have a hard time wrapping my head around why this is happening. To your observation @MarkLyck, I do see that even after deleting all items from the items prop, useNode still thinks the dom is the last existing <button /> although that doesn't even exist in the actual DOM any more.