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

xq niexq nie
2 min read

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

🏠 Homepage

Homepage

📦 Install

  yarn add @oyyds/react-auto-sizer  # or npm i @oyyds/react-auto-sizer -S

🔨 Use

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

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

🧩 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]);

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
}

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

10
Subscribe to my newsletter

Read articles from xq nie directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

xq nie
xq nie