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

Idea: add skipResize callback #152

Closed cscheffauer closed 3 years ago

cscheffauer commented 3 years ago

I've came across the use case that a skip of the update is not only useful on mount, but also conditionally (like having overflow elements and just want a change when the overflow elements change).

To achieve this, i've added a skipResize callback function as a prop to the react-resize-detector (see here).

Let me know if this is something you want to put in. I can create a pull request for it. 💯

Thanks and have a great day!

maslianok commented 3 years ago

@cscheffauer thank you for your suggestion!

I think you can achieve the same result by setting handleWidth and handleHeight to false.

Moreover, it's strongly recommended to set these props to false in case you don't need to handle them or you know that it's a constant value.

cscheffauer commented 3 years ago

@maslianok I've tried this and i wasn't able to cover the use case i have.

Imagine having a container component where u have tabs inside (left to right). This container has a specific width and only a specific amount of tabs is shown inside of the container (the one which don't fit are shown in an overflow area).

Now whenever u resize the container, the tabs should overflow or not (depending on how much space is left). This works with the react-resize-detector fine, but there is a performance issue with it. Imagine you resize the container just by let's say 2px. It will not cause the tabs to change (because a small change like this will not make tabs overflow). The resize detector fires an update (onResize callback) no matter what. So i got updates on my hook where i use the resize-detector even tough nothing in the ui changes really.

The idea of this skipResize function is, that the react-resize-detector updates conditionally and fires the onResize based on the width or height - which means I can do something like this:

// don't fire onResize when the tabs hasn't changed
  const skipResize = useCallback(
    (width?: number, height?: number) => {
      const newTabs = calcTabs(width, height);
      return newTabs === oldTabs;
    },
    [oldTabs, calcTabs]
  );

Let me know what you think! :)

maslianok commented 3 years ago

Well, let's make it clear - the main task of resize-detector is to notify you that the observed dimensions have changed. And then you decide how to react to these changes, right?

Now let's talk about your example. You must know width/height in order to calculate skipResize, right? Where do you take these values? The best and the most performant way to get them is inside the onResize callback

const onResize = useCallback((widh, height) => {
    const shouldRebuildUI = calculateTabsWidth(widh, height);

    if (!shouldRebuildUI) {
      return;
    }

    // rebuild logic goes here
}, []);

The library uses ResizeObserver API to calculate element's dimensions. And, again, you need these dimensions anyway to understand what to do next.

cscheffauer commented 3 years ago

@maslianok Right - i will check if I can refactor my current implementation using the onResize callback only 👍🏻 thanks a lot!