JavaScript >> Javascript チュートリアル >  >> React

React のアニメーションで条件付きレンダリングを使用する方法

この記事では、FadeIn/FadeOut 効果を使用した React での条件付きレンダリングの例をまとめてコーディングします。
ReactCSSTransitionGroup などのライブラリを使用してそれを達成することもできますが、サードパーティのライブラリを使用せずに条件付きレンダリングを使用して単純なアニメーションをコーディングする必要がある場合は、適切な場所にいます 😊

問題は何ですか:

ここで説明しようとしていることを理解するには、まず、react での条件付きレンダリングの重要性と、ページ内の要素のマウント/マウント解除 (フェードイン/フェードアウト) をアニメートするためのさまざまなアプローチについて確認する必要があります。

条件付きレンダリングなし:

HTML/CSS と JS (条件付きレンダリングなし) の助けを借りて、キーフレームとアニメーションの CSS プロパティを使用して不透明度を徐々に変更するか、CSS プロパティを移行するだけで実現できます。


import { useState } from "react";
import "./styles.css";

const mountedStyle = { animation: "inAnimation 250ms ease-in" };
const unmountedStyle = {
  animation: "outAnimation 270ms ease-out",
  animationFillMode: "forwards"
};

export default function App() {
  const [showDiv, setShowDiv] = useState(false);
  return (
    <div className="App">
      <button onClick={() => setShowDiv(!showDiv)}>Show/Hide</button>
      <div
        className="transitionDiv"
        style={showDiv ? mountedStyle : unmountedStyle}
      ></div>
    </div>
  );
}

Style.css

.transitionDiv {
  background: red;
  height: 100px;
  width: 200px;
  margin: 0 auto;
}

@keyframes inAnimation {
  0% {
    opacity: 0;
    visibility: hidden;
  }
  100% {
    opacity: 1;
    visibility: visible;
  }
}

@keyframes outAnimation {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    visibility: hidden;
  }
}

デモ:

リンク

ご覧のとおり、ShowDiv の値に基づいて、Mount/UnMount Style を設定し、トランジションを開始して影響を与えることができます。
プロパティ opacity は (0-1) の間の数値設定を持つことができるため、トランジションで指定された期間全体でキーフレームを計算できます。

PS :序数/計算可能なプロパティでのみ移行できます (これを考える簡単な方法は、数値の開始値と終了値を持つ任意のプロパティです..ただし、いくつかの例外があります)。

したがって、この場合、バイナリ設定 (可視/非表示) を持つ可視性プロパティは異なる動作をします。したがって、遷移時間が経過すると、プロパティは単純に状態を切り替えます。これは遅延として表示されますが、実際には遷移アニメーションの最後のキーフレームとして表示され、中間のキーフレームは計算されていません

条件付きレンダリングで React がもたらす違いは何ですか?

上記のアプローチでは、可視性プロパティのトランジションを使用しています。このプロパティは、要素を表示するかどうかをブラウザに伝えますが、ブラウザはそれを独自のスペースを取り、ページ内の他の要素の流れに影響を与える要素として扱います.

プロパティ height:0 または display:none をトランジションの終了時に設定するようなトリックを見つけたとしても、これは非表示になり、display:none はドキュメント レイアウトからも削除されますが、要素は DOM オブジェクトに残ります。

React では、条件付きレンダリングは JavaScript 条件と同様に機能します。 if/else ステートメントに基づいて、React は DOM オブジェクトを効率的に処理し、要素を非表示にするか表示するかを決定します。したがって、react の条件付きレンダリングを使用すると、DOM オブジェクトに不必要な不要な要素が含まれなくなります。これにより、コードのスムーズな実行、デバッグ、および設計が改善されます。

BUTTTTTT … React の条件付きレンダリングの効率性を活用し、同時に、React が要素を非表示にすることを決定したときに、DOM オブジェクトに存在しないものにトランジションまたはアニメーションを適用するにはどうすればよいでしょうか :) ?今、目の前にあるすべての問題を見ることができます。

上記の例に単純な条件付きレンダリングを追加しようとすると、次のようになります。

//...

export default function App() {
  const [showDiv, setShowDiv] = useState(false);
  return (
    <div className="App">
      <button onClick={() => setShowDiv(!showDiv)}>Show/Hide</button>
//Conditional Rendering
 { showDiv &&
      <div
        className="transitionDiv"
        style={showDiv ? mountedStyle : unmountedStyle}
      ></div>
}
    </div>
  );
}

Div を非表示にしようとするとアニメーションが失われることに気付くでしょう。これは、条件付きレンダリングを使用すると、React が遷移の開始前に DOM オブジェクトから Div を削除するためです。

この問題を解決するには、次の 2 つの方法を使用できます。

- OnAnimationEnd イベントの使用:

React は、いくつかのイベントをキャッチし、キャプチャ フェーズでそれらを処理するための組み込みのイベント ハンドラーを提供します。 React コンポーネントは preventDefault() や stopPropagation() などのネイティブ イベントを使用できます ...

私たちの場合、コンポーネントをアンマウントするときにアニメーションの遷移をキャッチし、この段階でより多くの制御を行うことに関心があります。これは次の方法で実行できます:

onAnimationEnd — このイベントは、アニメーションが終了した瞬間にトリガーされます。

コーディングしましょう:

//...

export default function App() {
  const [isMounted, setIsMounted] = useState(false);
  const [showDiv, setShowDiv] = useState(false);
  return (
    <div className="App">
      <button onClick={() => {
        setIsMounted(!isMounted)
        if (!showDiv) setShowDiv(true); //We should Render our Div
      }
      }>Show/Hide</button>

      { //Conditional Rendering
        showDiv && <div
        className="transitionDiv"
        style={isMounted ? mountedStyle : unmountedStyle}
        onAnimationEnd={() => { if (!isMounted) setShowDiv(false) }}
      ></div>}
    </div>
  );
}

ご覧のとおり、レンダリングを制御する Show Div は、Animation Ends まで待機し、その後 false に切り替わります。 onAnimationEnd イベント トリガーのおかげです。
ユーザーがボタン (表示/非表示) をクリックしたかどうかを示す新しい変数 isMounted も導入します。

デモ:

リンク

- シンプルなカスタム フックのコーディング:

これを解決するために、アンマウント ステージを遅らせ、React が DOM オブジェクトから要素を削除する前にトランジションを終了させる単純な関数をコーディングできます。

この関数は、値を false に切り替える前に、変数 showDiv に遅延時間を与えます。


import React, { useEffect, useState } from "react";

function useDelayUnmount(isMounted, delayTime) {
  const [showDiv, setShowDiv] = useState(false);
  useEffect(() => {
    let timeoutId;
    if (isMounted && !showDiv) {
      setShowDiv(true);
    } else if (!isMounted && showDiv) {
      timeoutId = setTimeout(() => setShowDiv(false), delayTime); //delay our unmount
    }
    return () => clearTimeout(timeoutId); // cleanup mechanism for effects , the use of setTimeout generate a sideEffect
  }, [isMounted, delayTime, showDiv]);
  return showDiv;
}

ユーザーがボタン (表示/非表示) をクリックしたかどうかを示す新しい変数 isMounted を導入します。これは、 useDelayUnmount が ShowDiv にその値を切り替える前に一定の時間を与え、DOM から削除する前にアニメーションが Div 要素に影響を与えることに基づいています。 /P>

完全版 :


import React, { useEffect, useState } from "react";

function useDelayUnmount(isMounted, delayTime) {
  const [showDiv, setShowDiv] = useState(false);
  useEffect(() => {
    let timeoutId;
    if (isMounted && !showDiv) {
      setShowDiv(true);
    } else if (!isMounted && showDiv) {
      timeoutId = setTimeout(() => setShowDiv(false), delayTime); //delay our unmount
    }
    return () => clearTimeout(timeoutId); // cleanup mechanism for effects , the use of setTimeout generate a sideEffect
  }, [isMounted, delayTime, showDiv]);
  return showDiv;
}

const mountedStyle = { animation: "inAnimation 250ms ease-in" };
const unmountedStyle = {
  animation: "outAnimation 270ms ease-out",
  animationFillMode: "forwards"
};

export default function App() {
  const [isMounted, setIsMounted] = useState(false);
  const showDiv = useDelayUnmount(isMounted,250);

  return (
    <div className="App">
      <button onClick={() => setIsMounted(!isMounted)}>Show/Hide</button>

//Conditional Rendering
 { showDiv &&
      <div
        className="transitionDiv"
        style={isMounted ? mountedStyle : unmountedStyle}
      ></div>
}
    </div>
  );
}


デモ:

リンク

以上です。何か新しいことを学んでいただければ幸いです :)


  1. JavaScript でウェブカメラをブラウザにストリーミングする

  2. オープンソース ツールを使用したフルスタック Nodejs アプリケーションのモニタリング

  3. オプティミスティックなUIのトリックが明らかに!