skip to Main Content

What is the correct way to do animations when removing something from the DOM?

It seems like no matter what I do, when I remove something form the dom, it doesn’t trigger a re render until the items are removed and then it snaps away out of view instead of transitioning before it removes the data. Here is an example of something I’ve tried.

  const [isExpanded, setIsExpanded] = useState(false);
  const [isVisible, setIsVisible] = useState(false);

  const toggleReplies = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);

    if (isExpanded) {
      setIsVisible(false);
      setTimeout(() => {
        setIsExpanded(false);
      }, 300);
    } else {
      setIsExpanded(true);
      setIsVisible(true);
    }
  };

  return (
    <View style={styles.container}>
      <Button title="Toggle Replies" onPress={toggleReplies} />
      {isVisible && (
        <View style={styles.replyBox}>
          <Text>This is a reply!</Text>
        </View>
      )}
    </View>
  );
};

2

Answers


  1. This is a common problem for animating the react components and elements, react is creating and destroying the dom nodes, so the browser does not apply any styles to elements that are non existing.

    2 options to achieve what you want, just change the styles and keep the nodes in dom, or you can use https://reactcommunity.org/react-transition-group/css-transition for adding "exit", "enter" styles to elements just before they will get destroyed / created.

    Login or Signup to reply.
  2. Christopher.

    Animating elements out upon removing them from the DOM can be complex because React removes the element without any further ado, and for that reason, the element simply "pops" out and doesn’t animate away as expected. There are two solid approaches to fix this:

    1. Make use of React Transition Group:

    This allows you to easily add "enter" and "exit" animations for your components.

    1. Install the Library:

      npm install react-transition-group
      
    2. Use inside your component:

      import React, { useState } from 'react';
      import { CSSTransition } from 'react-transition-group';
      import './styles.css'; // Include CSS animations here
      
      const MyComponent = () => {
        const [isVisible, setIsVisible] = useState(true);
      
        return (
          <div>
            <button onClick={() => setIsVisible(!isVisible)}>
              Toggle Replies
            </button>
            <CSSTransition
              in={isVisible}
              timeout={300}
              classNames="fade"
              unmountOnExit
            >
              <div className="replyBox">
                <p>This is a reply!</p>
              </div>
            </CSSTransition>
          </div>
        );
      };
      
      export default MyComponent;
      
    3. Define your CSS animations in styles.css:

      .fade-enter {
        opacity: 0;
      }
      .fade-enter-active {
        opacity: 1;
        transition: opacity 300ms;
      }
      .fade-exit {
        opacity: 1;
      }
      .fade-exit-active {
        opacity: 0;
        transition: opacity 300ms;
      }
      

    2. Eliminating Waste:

    Another solution is to postpone the state change which makes the element leave the DOM tree until the end of the animation.

    1. Add functionality to the toggleReplies function:

      const toggleReplies = () => {
        LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
      
        if (isExpanded) {
          setIsVisible(false);
          setTimeout(() => {
            setIsExpanded(false);
          }, 300); // Match this classname with your CSS animation
        } else {
          setIsExpanded(true);
          setIsVisible(true);
        }
      };
      
    2. Add your CSS animation:

      .replyBox {
        opacity: 1;
        transition: opacity 300ms;
      }
      .replyBox.hidden {
        opacity: 0;
      }
      
    3. Add conditional class in JSX:

      return (
        <View style={styles.container}>
          <Button title="Toggle Replies" onPress={toggleReplies} />
          {isExpanded && (
            <View style={[styles.replyBox, !isVisible && styles.hidden]}>
              <Text>This is a reply!</Text>
            </View>
          )}
        </View>
      );
      

    Using React Transition Group is the most robust and flexible solution, especially if you need more complex animations. Other method is simpler but less flexible.

    Hope this helps! Just tell me if you want any more questions.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search