無制限レンダリング...でもUseCallbackの

8059 ワード

プロジェクトでは、useEffectfetchを使用する必要があり、無限レンダリングが発生します.無限レンダリングの原因を特定し,useEffect()の流れをさらに考えるきっかけを提供し,useCallback()をさらに最適化する方法で理解した.
次のコードは、現在のパス情報を含むオブジェクトの探索値をuseLocation() hooksを用いて取得し、対応するデータを取得するコードである.
const [category, setCategory] = useState([]);

useEffect(() => {
    async function fetchAndSetCategory() {
      const response = await fetch(`${API.MenuList}${location.search}`);
      const data = await response.json();
      setCategory(data.results);
    }
    fetchAndSetCategory();
	 }, [category]);         *// 수정 전 코드* 
	 }, [location.search]);     *// 1차 수정 후 코드* 
初期の論理は、カテゴリstateを変更するたびにurlを変更することである.useEffect의 dependencyにcategory stateを直接加えた結果、useEffect無限ループに陥り、バックエンド無限fetchが破棄される.
これはjavascriptでは、関数がオブジェクトとみなされ、同じコードの関数でもメモリアドレスに基づいて参照比較され、厳密なピア演算子(===)を使用して2つの関数を比較するとfalse値が生成されるためです.
したがって、次のコードAPIの関数fetchAndSetCategory()が呼び出され、${location.search}を変更するかどうかにかかわらず、要素をレンダリングするたびに新しい参照値に変更され、ステータスの変更によりuseEffectが実行され、新しいレンダリングの悪循環が繰り返される.
そのため、初めてdependency[location.search]を加え、URL変更時にuseEffectを実行し、無限ループから抜け出した.ただし、レンダリングのたびにuserEffect内の関数が呼び出され、不要なレンダリングが発生します.
2回目は、以下に示すように、これよりも最適化されたコードuseCallback hooksが使用される.useCallback()は、依存性が変化した場合、以前に記憶された関数自体と比較して他の場合にのみレンダリングされる.構成部品を再ロードしても.  fetchAndSetCategory()関数の基準値を同じに保つことができる.だから、私が思ったように、  useEffect()を超える関数は  location.search  値が変更されない限り、再呼び出されません.
useCallback()を使用した二次修正コード
const fetchData = useCallback(() => {
    async function fetchAndSetCategory() {
      const response = await fetch(`${API.MenuList}${location.search}`);
      const data = await response.json();
      setCategory(data.results);
    }
    fetchAndSetCategory();
  }, [location.search]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);