'Observe changes to a DOM node's ClientRect

I have a component which will leverage context in order to register a dom node and add it into a QuadTree.

export default class SelectableGroup extends React.PureComponent {
  getChildContext() {
    return {
      register: this.register,
      unregister: this.unregister,
    };
  }

  private tree: QuadTree<string, HTMLElement> = new QuadTree();

  registerNode = (key: string, node: HTMLElement) => {
    const { left, top, height, width } = node.getBoundingClientRect();
    this.tree.set(key, {
      minX: left,
      maxX: left + width,
      minY: top,
      maxY: top + height,
    });
  }

  unregisterNode = (key: string) => {
    this.tree.delete(key);
  }

  public render() {
    return (<div>{this.props.children}</div>);
  }
}

This will run on an componentDidMount, meaning it is only registered once. However, I must keep the position up to date -- whenever the node moves or changes position (whether by scroll, resize, etc), I want to receive a notice of that change and update its position in my QuadTree.

Ideally, what I want to do is observe changes to the node and update the registry appropriately. Here's a "sketch" of what my goal is:

registerNode = (key: string, node: HTMLElement) => {
  node.observe(({ left, width, top, height }) => {
    this.tree.set(key, {
      minX: left,
      maxX: left + width,
      minY: top,
      maxY: top + height,
    });
  }));
}

Which is to say, whenever the ClientRect of the node changes, fire a callback which will update it in the store.

Does any API in javascript exist for this?



Solution 1:[1]

I made a hook to do this, called @lbfalvy/usedimensions. As far as I'm aware it's the only client rect tracker that works in all cases regardless of the reason for the change. I didn't debounce it because the point of this is to update positions instantly, but remember that by the nature of the task this will rerender on every single frame, tens of times per second while scrolling which is very inefficient so you should probably exhaust all other options first.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Lőrinc Bethlenfalvy