LoginSignup
1
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-01-13

ReactTransitionGroup

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

ReactCSSTransitionGroup

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

何がしたいのか

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

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

ReactTransitionGroupの説明(英語の方は公式)

en: https://ja.reactjs.org/docs/animation.html

ja: 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のみ
  • 追加、削除の処理を明示的に行った場合はEnterLeaveが発火
  • componentWillAppearはデフォルトのcomponentDidMountと同時に実行するため、コールバックで処理を遅らせてもコンポーネントの表示を遅らせることはできない。

    //この時点で既にマウント完了している
    componentWillAppear(callback){
        console.log('top willappear')
        setTimeout(()=> {
            callback()
        }, 2000)
    }
    
    componentDidAppear(){
        console.log('top didappear')
    }
    
  • componentWillLeaveはコールバックが実行されるまでDOMをキープしてくれるので、コンポーネントの削除を遅らせる事が可能。

    //この時点ではまだ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
    - ルートの遷移をアニメーション化したいと思うことがよくありますが、これは適度に使うことで楽しい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

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

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0