maslianok / react-resize-detector

A Cross-Browser, Event-based, Element Resize Detection for React
http://maslianok.github.io/react-resize-detector/
MIT License
1.25k stars 91 forks source link

onResize doesn't work when min-height is set #244

Closed spiotrowska closed 1 year ago

spiotrowska commented 1 year ago

Hi, I have question about min-height. When I set the min-height property on my div, the onResize event doesn't work when content inside div is deleted. Is this situation correctly?

Surprisingly, when I add a border to div, it works fine but I don't need border on my component.

const Test: FC = () => {
  const [isButtonClicked, setIsButtonClicked] = useState(false);
  const [heightEl, setHeightEl] = useState(0);

  const { ref } = useResizeDetector({
    onResize: (_?: number, height?: number) => {
      console.log("onResize content", height);
    },
  });

  return (
    <div ref={ref}>
      <button
        type="button"
        onClick={() => setIsButtonClicked(!isButtonClicked)}
      >
        Switch content
      </button>
      <ReactResizeDetector
        handleHeight
        handleWidth
        observerOptions={{ box: "content-box" }}
        onResize={(width, height) => {
          console.log("onResize", height, width);
          if (height) setHeightEl(height);
        }}
      >
        <div
          style={{
            backgroundColor: "beige",
            minHeight: heightEl,
            // border: "1px solid red",
          }}
        >
          {heightEl}
          <div>dfjgnd skdjfnsdjk wkfjnsd</div>
          <div>dfjgnd skdjfnsdjk wkfjnsd</div>
          {isButtonClicked ? <div>fddfgdfgdfgve dfgs</div> : null}
        </div>
      </ReactResizeDetector>
    </div>
  );
};
snelsi commented 1 year ago

What are you trying to achieve with minHeight?

When you set the min-height property on your div, it ensures that the div will always have a minimum height even if its content is removed. However, the resizeObserver won't trigger onResize event when the inner content is deleted because the div itself is still maintaining its minimum height.

Adding a border to the div might be affecting the way the browser calculates the height, potentially triggering the onResize event correctly. This behavior can be attributed to how the browser renders elements and calculates their dimensions when a border is present.

Generally, this code:

const [heightEl, setHeightEl] = useState(0);

<ReactResizeDetector onResize={(_, height) => setHeightEl(height)}>
  <div
    style={{
      minHeight: heightEl,
    }}
  />
</ReactResizeDetector>

Is not a good practice.

Depending on what you're trying to achieve, maybe you actually want to store a heightEl in a css-variable?

Or, just try to manually reset the heightEl when isButtonClicked changes

 useEffect(() => {
    // Manually trigger onResize when content is removed
    if (!isButtonClicked) {
      setHeightEl(0); // Reset the height
      setTimeout(() => {
        // Use a setTimeout to ensure the height change is detected
        const divHeight = ref.current?.clientHeight;
        if (divHeight) setHeightEl(divHeight);
      }, 0);
    }
  }, [isButtonClicked]);
spiotrowska commented 1 year ago

I've provided this test code to show my problem, but in project which I am working on, I am using min-height to hold height of each rows in boxes (to have the same height of each row, something like in Grid).

I use ResizeDetector to check the height of elements and set it to its maximum for each row in the same line, but the problem is when content is deleted, min-height blocks the onResize event.

Do you have any suggest how to deal with it?

snelsi commented 1 year ago

I think you can make all rows to have the same height with plain css, either by using flex: 1 1 auto or by using grid-auto-rows: 1fr

snelsi commented 1 year ago

Or by doing something like align-items: stretch, justify content: stretch, min-height: 100%