ReactTransitionGroupによって使える様になる特殊なライフサイクルメソッド

## ReactTransitionGroup

- Reactでトランジションを実現したいときの低レベルコンポーネント
- `ReactCSSTransitionGroup`よりも細かい設定を自前で実装したいときに使用

## ReactCSSTransitionGroup

- Reactでトランジションを実現したいときの高レベルコンポーネント

## 何がしたいのか

- ルーティング先のコンポーネントで特殊ライフサイクルメソッド（後述）を呼び出せる様にしたい

## Transition-groupに対して使えるライフサイクルメソッド

### ReactTransitionGroupの説明（英語の方は公式）

en: [https://ja.reactjs.org/docs/animation.html](https://ja.reactjs.org/docs/animation.html)

ja: [http://js.studio-kingdom.com/react/guides/animation](http://js.studio-kingdom.com/react/guides/animation)

### `**<ReactTransitionGroup>`タグの子コンポーネントで使用可能になる**

# `componentWillAppear()`

`componentWillAppear(callback)`

This is called at the same time as `componentDidMount()` for components that are initially mounted in a `TransitionGroup`. It will block other animations from occurring until `callback` is called. It is only called on the initial render of a `TransitionGroup`.

---

# `componentDidAppear()`

`componentDidAppear()`

This is called after the `callback` function that was passed to `componentWillAppear` is called.

---

# `componentWillEnter()`

`componentWillEnter(callback)`

This is called at the same time as `componentDidMount()` for components added to an existing `TransitionGroup`. It will block other animations from occurring until `callback` is called. It will not be called on the initial render of a `TransitionGroup`.

---

# `componentDidEnter()`

`componentDidEnter()`

This is called after the `callback` function that was passed to `[componentWillEnter()](https://ja.reactjs.org/docs/animation.html#componentwillenter)` is called.

---

# `componentWillLeave()`

`componentWillLeave(callback)`

This is called when the child has been removed from the `ReactTransitionGroup`. Though the child has been removed, `ReactTransitionGroup` will keep it in the DOM until `callback` is called.

---

# `componentDidLeave()`

`componentDidLeave()`

This is called when the `willLeave` `callback` is called (at the same time as `componentWillUnmount()`).

## 色々試した結果得た知見（暫定的）

- ReactTransitionGroupは直下の子コンポーネントにのみ反応するっぽい
- ルーティングで呼び出されるのは`Appear`のみ
- 追加、削除の処理を明示的に行った場合は`Enter`、`Leave`が発火
- `componentWillAppear`はデフォルトの`componentDidMount`と同時に実行するため、コールバックで処理を遅らせてもコンポーネントの表示を遅らせることはできない。

    ```jsx
    //この時点で既にマウント完了している
    componentWillAppear(callback){
    	console.log('top willappear')
    	setTimeout(()=> {
    		callback()
    	}, 2000)
    }
    	
    componentDidAppear(){
    	console.log('top didappear')
    }
    ```

- `componentWillLeave`はコールバックが実行されるまでDOMをキープしてくれるので、コンポーネントの削除を遅らせる事が可能。

    ```jsx
    //この時点ではまだDOMはキープされている
    componentWillLeave(callback){
    	setTimeout(()=> {
    		callback()
    	}, 2000)
    	console.log('top willleave')
    }

    //このタイミングでDOMが消える
    componentDidLeave() {
    	console.log('top didleave')
    }
    ```

    ## ルーティングによるコンポーネントの切り替えの際にEnterとLeaveを発生させたい

    - EnterとLeaveはコンポーネントの「追加」「削除」時に発生する。
    - そもそもReactのルーティングはコンポーネントの「追加」「削除」にあたるのか？
    - EnterとAppearの違いは？（現状ルーティングで発生しているのがAppear）

    ## AppearとEnterとLeaveの違い

    上の英文から解釈

    ### Appear（現状ルーティングで使えている）

    - 初期マウントされているコンポーネントで呼び出される。
    - ルーティングの場合最初に全てのコンポーネントを用意しているためこちらになる？

    ### Enter（現状ルーティングで使えていない）

    - 既存の TransitionGroupに**追加されたコンポーネントに対して、**componentDidMount() と同時に呼び出されます。コールバックが呼ばれるまで、他のアニメーションが発生しないようにブロックします。TransitionGroup の初期レンダリング時には呼び出されません。

    - 既存のTransitionGroupに追加されたコンポーネントで呼び出される（**新規追加**）。

    ### Leave（現状ルーティングで使えていない）

    - これは、ReactTransitionGroupから子が**削除されたときに**呼び出されます。子が削除されても、ReactTransitionGroupはコールバックが呼ばれるまで子をDOMに保持します。
    - TransitionGroupからコンポーネントが削除されたときに呼び出される。
    - ルーティングの際は、削除せずコンポーネントを切り替えているだけなので実行されない？

    つまり、**ルーティングはコンポーネントを入れ替えているだけで削除しているわけではないのでLeaveを呼び出せない？**

    ## 全てのルートを一つのReactTransitionGroupでラップして、かつその子孫のコンポーネント内でライフサイクルメソッドを使いたい

    - 直下に`Route`があるから反応しないのか？
 

    ### React Transition Group with Router

    [https://reactcommunity.org/react-transition-group/with-react-router](https://reactcommunity.org/react-transition-group/with-react-router)

    - ルートの遷移をアニメーション化したいと思うことがよくありますが、これは適度に使うことで楽しいUXになります。最初の方法はTransitionGroupですべてのルートをラップすることかもしれませんが、このアプローチはハックが必要で、RedirectのようなReact Routerのトリッキーなコンポーネントと一緒に使うと簡単にバラバラになります。各ルートにCSSTransitionを使い、それぞれのルートのin propを独自に管理する必要があります。
    - 主な課題は出口のトランジションです。React Routerは瞬時に新しいルートに切り替わるので、そこからトランジションするためには古いルートを長く維持しておく必要があります。幸いなことに、Routeのchildren propは関数も受け付けており、render propと混同してはいけません。レンダープロップとは異なり、children 関数はルートがマッチしているかどうかに関わらず実行されます。React Router は match オブジェクトを含むオブジェクトを渡しますが、これはルートがマッチしていれば存在し、そうでなければ null です。これにより、マッチの有無に応じてCSSTransitionのinプロップを管理できるようになりました。
    - 終了トランジションでは、ルートの内容が消えるまで残ってしまうため、スタイリング上の問題が発生する可能性があります。ルートがお互いのレイアウトに影響を与えないようにしてください。例えば、絶対配置や固定配置を使用することで、ドキュメントの流れからルートを削除することができます。
    - 注意：React トランジショングループを React Router で使用する場合、Switch コンポーネントは最初に一致する Route のみを実行するため、Switch コンポーネントの使用を避けるようにしてください。そうすると、終了するルートが現在の URL と一致しなくなり、子関数が実行されなくなるため、終了遷移を実現できなくなります。

    Transitionで全部をラップするのはやめとけみたいな事が書いてある。

    ## もしかしてReactTransitionGroup使わないほうがいい？

    [https://agm1984.medium.com/how-to-manage-page-transition-animations-in-react-ba09c66655c6](https://agm1984.medium.com/how-to-manage-page-transition-animations-in-react-ba09c66655c6)

    この記事ではTransitionGroupとTransitionでやっている

    この記事通りにやるとそれぞれフックは取れるけど、コンポーネントごとに独立して存在するので処理を止めるという事が難しい