Stanko / react-animate-height

Lightweight React component for animating height using CSS transitions. Slide up/down the element, and animate it to any specific height.
https://muffinman.io/react-animate-height
MIT License
756 stars 53 forks source link

`onHeightAnimationEnd` is triggered before <img> onLoad #139

Closed Bdragon93 closed 1 year ago

Bdragon93 commented 1 year ago

Hi again,

Code example https://codesandbox.io/s/react-animate-height-animate-height-when-content-changes-forked-1fqvnu?file=/src/index.js

Expected behavior

Possible Solution

Steps to Reproduce (for bugs)

  1. Clear the browser cache every time refresh the page, (set network throttling to slow if needed) => wrong height as the first screenshot.
  2. Click toggle button => wrong height as the 2nd screenshot.

Screenshots Screenshot 2023-04-18 at 13 58 33 Screenshot 2023-04-18 at 13 58 41

Your Environment Version used: 2.1.0 / 3.1.1 OS: MacOS 13.3.1 Browser: Brave/Chrome Version: 112.0.5615.121

Additional context

Stanko commented 1 year ago

That is a race condition that is outside of the AnimateHeight. You would need to handle content mutations and load events in order to pull off something like that.

You didn't paste your code, but if I understood you correctly it would look something like this:

const [height, setHeight] = useState('auto');
const imgRef = useRef(null);

const updateImageHeight = () => {
  const imageHeight = imgRef.current.clientHeight;
  setHeight(imageHeight);
} 

<AnimateHeight height={height}>
  <img onLoad={updateImageHeight} ref={imgRef} />
</AnimateHeight>

Hope that helps!

Stanko commented 1 year ago

This might be interesting for your usecase as well: https://github.com/Stanko/react-animate-height/issues/122#issuecomment-1093797649

Bdragon93 commented 1 year ago

@Stanko oops, so sorry I pasted a wrong one :( , I edited description with a codesandbox link. anw, that's right it's a race condition, your suggestion would work wells if the children is only , in my case would need to check if the image is loaded or not to set the height with + imgRef.current.clientHeight or not.

I just want to know if it's handled from RAH automatically, if not I can handle by component state, what frustrating is we need to create every single flag to check for each image is loaded or not.

Thanks so much for your support!

Stanko commented 1 year ago

Sorry, I completely forgot about this.

I updated your sandbox and added ResizeObserver: https://codesandbox.io/s/react-animate-height-resize-observer-7q4xc2?file=/src/index.js:168-675

const AutoHeight = ({ children }) => {
  const [height, setHeight] = useState("auto");

  useEffect(() => {
    // Updated to refs once AnimateHeight adds a ref mechanism
    const contentDiv = document.querySelector(".auto-content");

    const resizeObserver = new ResizeObserver(() => {
      setHeight(contentDiv.clientHeight);
    });

    resizeObserver.observe(contentDiv);
  }, []);

  return (
    <AnimateHeight height={height} contentClassName="auto-content">
      {children}
    </AnimateHeight>
  );
};

I'm not happy about querySelector, I need to add a way to get refs from AnimateHeight.

Hope this helps!

EDIT: I made code a bit more concise.

Stanko commented 1 year ago

Link for reference https://github.com/Stanko/react-animate-height#animate-height-on-content-change