6

I want to know how React handles a Render that is called during a component's animation. In the below example, a component is rerendered

Say there is a state change to the component during the component's animation, and so the component is re-rendered. Will react replace the physical DOM or will it recognize that the component is in mid-animation? Here is what I think will happen

Step 1: Component Mounts The component is mounted to the physical DOM for the first time. The component's animation lasts 60 seconds. The component has a change state timer that will go off in 30 seconds. Meanwhile, react saves the virtual DOM at the time of mounting.

Step 2: State change is triggered and the component re-renders After 30 seconds, a state change will occur in the parent, and the component will be re-render. At this point the component is in mid animation, and using react-transition-group, the "className-active" css class is being applied to the child. React will now compare the present virtual DOM with the older virtual DOM. The virtual DOMs are different as the child now has the active class applied to it (as opposed to the "enter" class). As a result, react will insert the updated component into the physical DOM (even though the physical DOM does not need to be updated!). Therefore, the screen will flicker...

Here is the code describing the scenario above

import React from 'react'
import CSSTransition from 'react-transition-group'
                                                                                                                                                                                                                     ```
class ExampleComponent extends React.Component {
      constructor(props) {
           super(props);
           this.state = {reRender : false};
           setTimeout(() => {this.setState({reRender: true})}, 30000) 
           /* 30,000 ms is 30 seconds. 
              Set state will fire in 30 seconds, and the parent component will 
             rerender itself and the     
           */
     }
      render()  {
          return (
                <CSSTransition
            appear = {true}
            in = {true}
            classNames = 'test'
            timeout = {60000}>
                <span> test </span>
        </CSSTransition>
          )

      }

}

Here are the relevant css classes

.test-appear, test-enter{
       opacity : 1;
}
.test-appear-active, .test-enter-active {
      opacity: 0; 
      transition: opacity; 
      transition-duration: 60000;
}
.test-appear-done, .test-enter-done {
      opacity: 0;    
}

Given this code, I would like to be walked step by step what happens in the react lifecycle, and the virtual DOM. Will the physical DOM be updated after 30 seconds or will react recognize it is in mid animation? How is the virtual DOM saving previous state?

2 Answers2

3

On this case CSSTransition is keeping internal state to know in which phase of the animation it is.

React does not reset the state of the CSSTransition instance because it knows it refers to the same element (React relies on the type of component and position on the tree to decide if it is the same element, or on the key prop when defined)

Because the internal state of CSSTransition is the same it's render method renders the same css class before and after the state change on your component.

See your example it working without flicker https://codesandbox.io/s/hopeful-shaw-c9ldr

CSSTransition might change the state in response to a change in any of the props you pass to it (which in this case does not even occur) but that's dependant on the CSSTransition implementation.

Finally, if you passed a different key to CSSTransition it would reset the animation as React would consider it a new component, so would unmount the previous one and mount a new one, with a new internal state.

see the example with the animation reseting here: https://codesandbox.io/s/jolly-maxwell-2ihkf

Tiago Coelho
  • 5,023
  • 10
  • 17
1

React doesn't care about animations. All it cares is making sure the DOM is updated according to changes in the vDOM.

When you manually remove elements from the DOM mid-animation, the animation will just stop. React will do the exact same, namely, any change to the tree (not including prop changes that don't alter the tree structure) will unmount and remount the involving elements immediately on the next render cycle.

In your case, since the tree didn't change, it won't tear down any elements. render() will be called, react will compare the old and new version of the vDOM and will just modify the props if there are any changes. But your manual rerender with the state change won't affect the vDOM in any way

Refer to the Reconciliation docs for more information.

Mordechai
  • 15,437
  • 2
  • 41
  • 82
  • How come the vdom didn’t change on my second call to Render()? On the initial call to render the vdom has a With the css enter class applied to it. On the second call of render() the dom has the entering class applied to it. The key question I think is: has the vdom changed at all? Does it know that the dom has changed? If not, then the vdom and the dom are out of sync, but as the vdom remained the same on the second call of render() , nothing new will be inserted into the dom on the second call of render() – michael_fortunato Jan 22 '21 at 20:38
  • Even if the vDOM changes, it might only be prop changes (in your case, `className`) and it won't tear down the existing dom elements, just modify them. – Mordechai Jan 22 '21 at 20:51
  • Maybe I didn't make it clear enough, the actual animation happens in the css realm and nothing changes in the dom or vDOM while animating – Mordechai Jan 22 '21 at 20:59
  • I think the DOM changes. When I inspect element and the animation is triggered, I see the entering class get applied to the DOM. I am wondering if the vdom is aware of that. – michael_fortunato Jan 22 '21 at 21:00
  • 1
    Yes, that's a change in the `className`, controlled by css transition, but still your call to rerender after 30 seconds has no effect – Mordechai Jan 22 '21 at 21:16
  • How is the vdom aware of the change in className in the dom? I thought the vdom is only constructed during render() – michael_fortunato Jan 22 '21 at 23:34
  • you should check CSSTransition code... It is also a react component with state of it's own... – Tiago Coelho Jan 27 '21 at 10:54