DEV Community

Cover image for Implement a react component that automatically calculates width and height based on ResizeObserver
niexq
niexq

Posted on

Implement a react component that automatically calculates width and height based on ResizeObserver

🏠 Homepage

Homepage

📦 Install

  yarn add @oyyds/react-auto-sizer  # or npm i @oyyds/react-auto-sizer -S
Enter fullscreen mode Exit fullscreen mode

🔨 Use

import AutoSizer from '@oyyds/react-auto-sizer';

const AutoSizeComponent = () => {
  return (
    <div>
      <AutoSizer>
        {({ width, height }) => (
          <div
            style={{
              width,
              height,
            }}
          >
            content
          </div>
        )}
      </AutoSizer>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

🧩 Business scene

Now most business scenarios need to be compatible with big data, such as big data table, big data tree, big data drop-down box, etc., and all big data components need to specify width and height, Most of the actual business interface needs to calculate the width and height in real time, and react-auto-sizer is to complete the task of automatic calculation of width and height.

visiblearea

🧑‍💻 Coding

At the beginning of the pre-research, windows was bound to resize, but due to resize, there will be performance problems when the window changes, and some extreme pixels will appear jitter. ;

ResizeObserver, the interface can listen to changes in the content area of Element or the bounding box of SVGElement. The content area needs to be subtracted from the padding. -- from MDN

ResizeObserver best choice, use react hook useEffect,The core code is as follows:


const updateState = useCallback(
    (newWidth: number, newHeight: number, entry: ResizeObserverEntry) => {
      // update state
      // onResize width, height
      props.onResize({ width: newWidth, height: newHeight }, entry);
    },
    [childParams, disableHeight, disableWidth, onResize],
  );

const observer = useMemo(
    () =>
      new ResizeObserver((entries: ResizeObserverEntry[]) => {
        for (const entry of entries) {
          const contentRect = entry.contentRect;
          const width = Math.trunc(contentRect?.width || 0);
          const height = Math.trunc(contentRect?.height || 0);
          updateState(width, height, entry);
        }
      }),
    [updateState],
  );

useEffect(() => {
    if (!_autoSizerRef?.current?.parentNode) {
      throw new Error('Not Found AutoSizer parentNode');
    }
    observer.observe(_autoSizerRef?.current?.parentNode as Element);
    return () => {
      observer.disconnect();
    };
  }, [observer]);
Enter fullscreen mode Exit fullscreen mode

Focus:

observer.observe(_autoSizerRef?.current?.parentNode as Element),listen parent dom node

contentRect: ResizeObserverEntry return a DOMRectReadOnly read-only property contentRect, object containing the new size of the observed element, property:

{
  "x": 0,
  "y": 0,
  "width": 300,
  "height": 200,
  "top": 0,
  "right": 300,
  "bottom": 200,
  "left": 0
}
Enter fullscreen mode Exit fullscreen mode

contentRect returns the content box, which is the size of the content area (for detailed reasons, please refer to Zhang Xinxu's introduction to ResizeObserver)

content-box

so contentRect.widthcontentRect.height is the width and height we need

⭐️ Thanks for reading

github:https://github.com/niexq/react-auto-sizer, Thanks for reading and welcome Star

🐳 Source of inspiration

react-virtualized-auto-sizer

ResizeObserver

Detect DOM size changes JS API ResizeObserver

Discussion (0)