(React)useMemoとuseCallback



useMemoとuseCallbackを学ぶ前に、

  • 関数型要素は関数のみです.関数型素子はjsxの関数を返すだけです.
  • 要素のレンダリングは、関数(要素)を呼び出すことによって実行されるユーザを指す.関数が実行されるたびに、内部宣言式(変数、または他の関数など)も再宣言されます.
  • 構成部品は、ステータスの変更や親から受け取ったアイテムの変更時に再レンダリングされます(さらに、子が最適化されていない場合でも、親から受け取ったアイテムは変更されず、デフォルトでは再レンダリングされます).
  • useMemo

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    文章の核心は、コメントを変換した値を返すことです.サブコンポーネントは、親コンポーネントからaおよびbという2つのpropsを受信することを想像する.サブエレメントでは、aおよびbが伝達されると、各値を異なる関数で加工(または計算)する新しい値を表示する役割を果たす.
    propsに渡されるパラメータを変更するたびに、サブエレメントがレンダリングされます.props.aのみが変更された場合、propsの値は以前と同じです.bも関数を呼び出してカウントしますか?
    簡単な例を見てみましょうuserMemoについて説明します
    Appコンポーネントは、ユーザから入力されたcolorおよびmovie値をinfoコンポーネントに渡し、infoコンポーネントは、渡されたcolorおよびmovieを適切なハングルに変換して文形式で表示します.
    //App.js
    
    import info from './info';
    
    const App = () => {
      const [ color, setColor ] = useState('');
      const [ movie, setMovie ] = useState('');
      
      const onChangeHandler = e => {
        if (e.target.id === 'color') {
          setColor(e.target.value);
        } else {
          setMovie(e.target.value);
        };
        
          return (
        <div className="App">
          <div>
            <label>
              What is your favorite color of rainbow ?
              <input id="color" value={color} onChange={onChangeHandler} />
            </label>
          </div>
          <div>
            What is your favorite movie among these ?
            <label>
              <input
                type="radio"
                name="movie"
                value="Marriage Story"
                onChange={onChangeHandler}
              />
              Marriage Story
            </label>
            <label>
              <input
                type="radio"
                name="movie"
                value="The Fast And The Furious"
                onChange={onChangeHandler}
              />
              The Fast And The Furious
            </label>
            <label>
              <input
                type="radio"
                name="movie"
                value="Avengers"
                onChange={onChangeHandler}
              />
              Avengers
            </label>
          </div>
          <Info color={color} movie={movie} />
        </div>
      );
    };
    
    export default App;
    // Info.js
    
    const getColorKor = color => {
        console.log("getColorKor");
        switch (color) {
          case "red":
            return "빨강";
          case "orange":
            return "주황";
          case "yellow":
            return "노랑";
          case "green":
            return "초록";
          case "blue":
            return "파랑";
          case "navy":
            return "남";
          case "purple":
            return "보라";
          default:
            return "레인보우";
        }
      };
    
      const getMovieGenreKor = movie => {
        console.log("getMovieGenreKor");
        switch (movie) {
          case "Marriage Story":
            return "드라마";
          case "The Fast And The Furious":
            return "액션";
          case "Avengers":
            return "슈퍼히어로";
          default:
            return "아직 잘 모름";
        }
      };
    
    
    const Info = ({ color, movie }) => {
      const colorKor = getColorKor(color);
      const movieGenreKor = getMovieGenreKor(movie);
    
      return (
        <div className="info-wrapper">
          제가 가장 좋아하는 색은 {colorKor} 이고, <br />
          즐겨보는 영화 장르는 {movieGenreKor} 입니다.
        </div>
      );
    };
    
    export default Info;

    例の実行画面
    Appコンポーネントの入力ウィンドウでは、カラー値を変更するとgetColorkor、getMovieGenereKorの2つの関数が実行され、movie値のみが変更されると、両方の関数が実行されます.useMemoをインポートすることで、colorkorとmovieGenerokorの計算部分をinfoコンポーネントのコードで以下のように変更できます.
    import React, { useMemo } from 'react';
    
    const colortKor = useMemo(() => getColorKor(color, [color]);
    const movieGenreKor = useMemo(() => getMovieGenreKor(movie), [movie]);
    useMemoを使用すると、依存配列に渡された値が変更された場合にのみ、アノテーションの期限切れの値が再計算されます.
    サンプルコードを直接変更して色値を変更する場合は、getColorKor関数のみが呼び出され、movie値が変更されるとgetMovieGenereKor関数のみが呼び出されることを確認できます.
    再計算の関数が非常に単純であれば性能の差は小さいかもしれませんが、再計算の論理が複雑であれば、不要な高価な計算を防止することができます.

    useCallback

    const memoizedCallback = useCallback(
      () => {
        doSomething(a, b);
      },
      [a, b],
    );
    この文章の核心は,注釈化された関数を返すことである.
    内部宣言式(変数、別の関数など)は、要素をレンダリングするたびに再宣言されます.userMemoを記述する例では、アプリケーション.jsのonChangeHandler関数は,内部のcolor,movie状態値が変化するたびに再宣言されることを意味する.ただしonChangeHandler関数はパラメータとして渡されるイベントオブジェクト(e)のstartgetである.ID値に基づいてsetStateを実行するだけなので、最初のインストール時に宣言して再利用すればいいのではないでしょうか.
    // App.js
    
    import React, { useState, useCallback } from 'react';
    
    const onChangeHandler = useCallback(e => {
      if (e.target.id === 'color') {
        setColor(e.target.value)
      } else {
        setMovie(e.target.value)
      }, []);
    App.jsにuseCalbackをインポートし、onChangeHandler関数の宣言を上のように置き換えます.最初のマウント時のみ、メモリに割り当てられているかどうかを判断するのは難しいですが、上記のようにします.
    サブエレメントが反応すると.memo()のようなコンポーネントを最適化し、関数をコールバックとして宣言するのに役立ちます.関数を再宣言するたびに、サブエレメントは伝達された関数が変化したと考えられるからです.
  • React.memo()を使用して関数型構成部品自体を囲む場合、渡されたpropsが変更されていない場合、親構成部品はコメントされた関数型構成部品(以前にレンダリングされた結果)を使用します.
  • 関数は,自分だけが同じであるため,親コンポーネントでコールバック関数(同じ関数であっても)を再宣言すると,コールバック関数をpropsとしてサブコンポーネントに渡す立場でpropsが変化したと考えられる.
  • ソース


    原文を調べる