Search code examples
javascriptreactjsreact-spring

Issues on animating a conditionally rendered component using React-spring


I am new with react-spring. I am having trouble animating a component whenever it unmounts. I have a simple card with an onClick handler that's responsible for conditionally displaying my Overlay component. The animation works fine when mounting (from & enter works), but when closing the overlay, the component just disappears without animation (leave does not work). I suspect it's because of the conditional rendering of the component but I've been struggling for hours trying to find a solution for this one. Any help would be appreciated!

My current code: https://codesandbox.io/s/dry-leftpad-h3vmv
What I'm trying to achieve: https://codesandbox.io/s/048079xzw

P.S. The latter is using mauerwerk's lib. I don't want to use that.


Solution

  • What you were missing is this:

    return expand.map(({ item, props, key }) => (
      item && <animated.div
      // ...etc
    

    When you're controlling the mounting of a single component with useTransition, you need to conditionally render it based on the item being passed. In your case, when it's false it won't render (which will unmount if already mounted) and when it's true it will render (mount if unmounted).

    Here's a working sandbox forked from yours: https://codesandbox.io/s/infallible-agnesi-cty5g.

    A little more info

    The first argument to useTransition is the list you want to transition. That watches for changes and sends back an array mapped with each item, a key and a style object (props) based on whether the item is truthy (entering) or falsy (leaving). So for a transition that mounts/unmounts a single element, conditionally rendering based on the truthiness of the item is key.

    Check out the examples again here and you'll see the differences between transitioning a list, a toggle between two elements, and a single item.

    For a list, no need to check for the existence of the item because the array changes.

    For toggling between two elements, you use the truthiness of item to determine which element to render.

    For a single element, item determines whether to render at all. This means it won't mount initially when you default to false, and will make sure you don't render 2 items whenever your isActive value changes.