# React Transition Group 源码浅析

## 1. 前言

之前做日历组件的时候,移动端需要实现一个从底部弹出的一个弹层组件，涉及到React动画的相关知识。

当时了解到 `react-transition-group`的相关用法，但是不确定在实现`2C`组件的时候，引入外部组件是否恰当，毕竟原则上来说，最希望的是`2C`组件能足够轻量级，无其它无效代码。

在时间紧急情况下，当时使用回调的形式实现: 即当 componentDidMount时，给对应的DOM添加向上弹出动画class。在 visible 属性为false时，添加向下收缩动画的class, 等动画执行完通过回调告诉别的组件做别的操作。

也能实现动画的功能，但是总觉得这样的组件不够通用，于是在空闲之余查看了 `React-Transition-Group`组件的`Transition`部分源码, 特有此文，以做记录。

## 2. 流程图

[画流程图工具](https://marketplace.visualstudio.com/items?itemName=joaompinto.vscode-graphviz): Graphviz (dot) language support for Visual Studio Code

![react-transition-group](https://user-images.githubusercontent.com/25051945/64064373-0ae9be80-cc33-11e9-992a-3a71859162e1.png)

```
// 此时再次点击，使得in变为false，步骤简化版 
用户点击 in = false 开始 
=> getDerivedStateFromProps(不做处理)
=> render: 依旧渲染 entered 样式
=> didUpdate(), prevProps(in为true)不等于this.props(in为false)
=> status 等于 entered, 故 nextStatus 为 exiting,执行 this.updateStatus(false,exiting)
=> 执行 this.performExit
=> this.props.onExit
=> this.safeSetState({status: exiting})
=> getDerivedStateFromProps: nextIn为false, 不执行任何操作
=> render: 渲染 exiting 的样式
=> didUpdate: prevProps 等于 this.props
=> this.updateStatus(false, null)
=> 执行this.safeSetState({status: exiting})回调: this.props.onExiting
=> this.onTransitionEnd(node, timeouts.exit, callback): 在 timeout时间之后执行callback回调,即执行 this.safeSetState({status: exited})
=> this.safeSetState({ status: exited }): 触发 getDerivedStateFromProps, nextIn为false, 不执行任何操作
=> render: 渲染 exited 样式
=> didUpdate: prevProps 等于 this.props
=> this.updateStatus(false, null)
=> 执行this.safeSetState({ status: exited })回调: this.props.onExited(node)
```

## 3. 总结

经过阅读，即该组件首先根据参数，确定初始的status，比如如果`props.unmountOnExit`为`true`,那么初始`status`为`UNMOUNTED`,则初始的时候不进行渲染。

之后，当接受到的`in` 属性发生变化的时候，如果属性值为true，则会执行`performEnter`,在 `performEnter` 中, 先`setState({status:'entering')`,之后过了`timeout`时间，执行`setState({status:'entered')`. 此外还会在适当的时机执行`this.props.onEnter`及`this.props.onEntering`等回调函数。

也就是, 如果接受到对应的属性，那么在不会一次性的`setState`到`entered`或者`exited`。而是在这中间穿插`entering`或者`exiting`的状态，将切换的状态传递给子组件去做动画。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yes-1-am.gitbook.io/blog/react-kai-fa-shi-jian/reacttransitiongroup-yuan-ma-qian-xi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
