React:在动画期间调用 Render()。怎么了?

React: Calling Render() during animation. What happens?

我想知道 React 如何处理组件动画期间调用的渲染。在下面的例子中,一个组件被重新渲染

假设在组件动画期间组件状态发生变化,因此组件是 re-rendered。 React 会替换物理 DOM 还是会识别组件在 mid-animation 中? 这是我认为会发生的事情

第 1 步:组件安装 该组件首次安装到物理 DOM。组件的动画持续 60 秒。该组件有一个更改状态计时器,该计时器将在 30 秒后关闭。同时,react在挂载的时候保存了virtualDOM

第二步:触发状态变化,组件re-renders 30 秒后,parent 中将发生状态变化,组件将变为 re-render。此时组件处于动画中间,使用 react-transition-group,“className-active” css class 被应用到 child。 React 现在会将当前虚拟 DOM 与旧虚拟 DOM 进行比较。虚拟 DOM 不同,因为 child 现在应用了活动 class(与“输入”class 相对)。因此,React 会将更新后的组件插入到物理 DOM 中( 即使物理 DOM 不需要更新!)。所以,屏幕会闪烁...

这是描述上述场景的代码

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>
          )

      }

}

这里是相关的cssclasses

.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;    
}

鉴于此代码,我想逐步了解 React 生命周期和虚拟 DOM 中发生的事情。物理 DOM 会在 30 秒后更新还是会反应识别它处于动画中期?虚拟 DOM 如何保存以前的状态?

React 不关心动画。它所关心的只是确保 DOM 根据 vDOM.

的变化进行更新

当您手动从 DOM 动画中删除元素时,动画将停止。 React 将做完全相同的事情,即对树的任何更改(不包括不改变树结构的 prop 更改)将在下一个渲染周期中立即卸载并重新安装涉及的元素。

在你的例子中,由于树没有改变,它不会拆除任何元素。 render() 将被调用,react 将比较 vDOM 的新旧版本,如果有任何变化,将只修改道具。但是您的状态更改手动重新渲染不会以任何方式影响 vDOM

有关详细信息,请参阅 Reconciliation 文档。

在这种情况下,CSSTransition 保持内部状态以了解它处于动画的哪个阶段。

React 不会重置 CSSTransition 实例的状态,因为它知道它指的是同一个元素(React 依赖组件的类型和在树上的位置来决定它是否是同一个元素,或定义时在 key 道具上)

因为 CSSTransition 的内部状态是相同的,所以它的渲染方法在组件状态更改前后呈现相同的 css class。

看到你的例子它没有闪烁https://codesandbox.io/s/hopeful-shaw-c9ldr

CSSTransition 可能会更改状态以响应您传递给它的任何道具的更改(在这种情况下甚至不会发生),但这取决于 CSSTransition 实现。

最后,如果你传递一个不同的 keyCSSTransition 它会重置动画,因为 React 会认为它是一个新组件,所以会卸载前一个组件并安装一个新组件,用一个新的内部状态。

在此处查看动画重置示例: https://codesandbox.io/s/jolly-maxwell-2ihkf