私は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
を書くことができます here :
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, useDeepCompareMemoize(dependencies))
}
useEffect
と同じように使用できます。
私はうまくいく解決策を見つけました。
LodashのusePrevious()
および_.isEqual()
を使用する必要があります。 useEffect()
内に、previousapiOptions
がcurrentapiOptions
。 trueの場合、何もしません。 falseの場合updateData()。
例:
_const useExample = (apiOptions) => {
const myPreviousState = usePrevious(apiOptions);
const [data, updateData] = useState([]);
useEffect(() => {
if (myPreviousState && !_.isEqual(myPreviousState, apiOptions)) {
updateData(apiOptions);
}
}, [apiOptions])
}
_
usePrevious(value)
は、useRef()
でref
を作成するカスタムフックです。
公式Reactフックのドキュメント から見つけることができます。
_const usePrevious = value => {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
_
apiOptions
を制御できないことが確かな場合は、ネイティブのuseEffectを https://github.com/kentcdodds/use-deep-compare-effect に置き換えてください。