1. ホーム
  2. javascript

[解決済み] react useEffect オブジェクトの比較

2022-11-24 17:01:28

質問

reactを使用しています。 useEffect フックを使い、オブジェクトが変更されたかどうかをチェックし、その後フックを再度実行しています。

私のコードは以下のようなものです。

const useExample = (apiOptions) => {
    const [data, updateData] = useState([]);
    useEffect(() => {
       const [data, updateData] = useState<any>([]);
        doSomethingCool(apiOptions).then(res => {               
           updateData(response.data);
       })
    }, [apiOptions]);

    return {
        data
    };
};

残念ながら、オブジェクトが同一であると認識されないため、実行され続けています。

以下のような例だと思います。

const objA = {
   method: 'GET'
}

const objB = {
   method: 'GET'
}

console.log(objA === objB)

おそらく JSON.stringify(apiOptions) が効いているのでは?

どのように解決するのですか?

使用方法 apiOptions を状態値として使用します。

カスタムフックをどのように消費しているのか分かりませんが、このように apiOptions を使って状態の値として useState を使えばうまくいくはずです。このようにして、カスタムフックにステート値として提供することができます。

const [apiOptions, setApiOptions] = useState({ a: 1 })
const { data } = useExample(apiOptions)

こうすることで、あなたが setApiOptions .

例1

import { useState, useEffect } from 'react';

const useExample = (apiOptions) => {
  const [data, updateData] = useState([]);
  
  useEffect(() => {
    console.log('effect triggered')
  }, [apiOptions]);

  return {
    data
  };
}
export default function App() {
  const [apiOptions, setApiOptions] = useState({ a: 1 })
  const { data } = useExample(apiOptions);
  const [somethingElse, setSomethingElse] = useState('default state')

  return <div>
    <button onClick={() => { setApiOptions({ a: 1 }) }}>change apiOptions</button>
    <button onClick={() => { setSomethingElse('state') }}>
      change something else to force rerender
    </button>
  </div>;
}

または

深い比較対象を書くこともできます useEffect というように ここで :

function deepCompareEquals(a, b){
  // TODO: implement deep comparison here
  // something like lodash
  // return _.isEqual(a, b);
}

function useDeepCompareMemoize(value) {
  const ref = useRef() 
  // it can be done by using useMemo as well
  // but useRef is rather cleaner and easier

  if (!deepCompareEquals(value, ref.current)) {
    ref.current = value
  }

  return ref.current
}

function useDeepCompareEffect(callback, dependencies) {
  useEffect(
    callback,
    dependencies.map(useDeepCompareMemoize)
  )
}

のように使うことができます。 useEffect .