In React, how to Render component with a set Height AND THEN immedietly re-render with Height set to 0 (for transitioning height)

To transition the height from auto to 0 using just HTML, CSS had its own trials. I solved this using Javascript, by

  1. Setting CSS transtion for the content height
  2. Finding the actual height of the content (using javascript content.style.scrollHeight)
  3. Then setting the content.style.height to the actual height.
  4. Ensuring the browser registered this change by page by using forcing DOM reflow content.clientWidth for example forces page reflow)
  5. Then immedietely following, set the height to 0px content.style.height = 0 (which will transition start transition)

However, now I'm trying to write the same sequence in React, within the onlick handler ...

Step 1 (I can do) - using {refs} to get the content.scroll.height.

Step 2 (I can kinda do) - using setState that will eventually feed through to the render method which will then update the content.style.height to the actual content height.

Step 3 (Not sure how to ensure the above step takes effect before moving to the next line)

Step 4 (I'm unsure) how to get step 3 - make the browser aware of the change - before immedietely continuing onto step 4.

I could setState for height to fullHeight - but this won't have immediete effect, so the next line setState to 0px, will just overwrite first setState and the transition from fullHeight to 0px will not happen.

Below is the working Javascript code that I would like to recreate but using React - also full JSfiddle here https://jsfiddle.net/mattlusty/rfdvbz16/2/)...

document.querySelector("button").addEventListener("click", () => {
  let content = document.querySelector(".content");
  let wasOpen = content.classList.contains("open");
  content.classList.toggle("open");

  // remove any explicit set height (to reveal the natural height)
  content.style.height = null;
  
  // get the actual full natural height
  let fullHeight = content.offsetHeight;

  if (wasOpen) {
  
    // set initial height explicitly
    content.style.height = fullHeight + "px";
    
    // force reflow
    content.offsetWidth;
    
    // set final height explicitly - which it will transition to
    content.style.height = "0px";
    
  } else {
  
    // set initial height explicitly
    content.style.height = "0px";
    
    // force reflow
    content.offsetWidth;
    
    // set final height explicitly - which it will transition to
    content.style.height = fullHeight + "px";
  }
});

1 answer

  • answered 2021-09-11 18:06 Mahi

    I think you are looking for ResizeObserver

    https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver

     componentDidMount() {
          let div = document.querySelector(id);  // <--- pass element id to observe
                this.resizeObserver.observe(div);
            }
        
      resizeObserver = new ResizeObserver(entries => {
                for (let entry of entries) {
                    let width = entry.contentRect.width;
                   this.setState({ width: width });
                }
            });
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum