简体   繁体   中英

Debounce jsx element's rendering in React

I am wondering if it is possible to debounce a jsx element's rendering. I have an animation of a panel expanding that has some content in it. If the panel is empty (just the background) the animation is smooth and works as expected. The animation and associated components are all from Material-UI. The issue arises when the content is in the panel already so the animation (width expansion) just skips out to the width of the content making the animation look choppy. Here is a similar example to what I am referring to. This code is my code I am using in my panel and they work the same in terms of the expansion. Only difference is the content in this example is just lorem ipsum so the animation appears to work fine. Is it possible to debounce the <CardContent /> component's rendering like this?

{ open &&
  (
    _.debounce(e => {
      return (
        <CardContent>
          {/*content in here*/}
        </CardContent>
      )
    }, 300)
  )
}

or something similar (this doesn't work) so the panel will be fully expanded through the animation before the content is rendered?

I'd like to add a comment however my reputation isn't above 50 yet so unfortunately I can't :p.

JS Animation

To answer your question, if you are using JavaScript animations like GSAP or AnimeJS you can have a state flag called. isAnimating = null . Then when your animation starts set the flag to true and when it's finished set it to false . Then in your render() method write a conditional render like this.state.isAnimating === false && <CardContent /> .

CSS Animation

If you are using CSS animation you can use the transitionend event to wait for the animation to end. Therefore you have to create a ref on the animating DOM element to which you can attach the event.

Does that help you a bit? Please let me know if you have any other questions.

Here is a solution using react spring library

  • I added a state variable in order to display or not the card content

     const [contentVisible, setContentVisible] = React.useState(false); 
  • I created a spring to handle the width transition, I set contentVisible to true as soon as the width approaches the 300

     const { width } = useSpring({ width: open ? 300 : 120, onFrame: ({ width }) => setContentVisible(width > 299.8) }); 
  • Finally, I created an animated card component

     const AnimatedCard = animated(Card); ... <AnimatedCard classes={{ root: classes.card }} style={{ width }}> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM