I am using react useEffect
hooks and checking if an object has changed and only then run the hook again.
My code looks like this.
const useExample = (apiOptions) => {
const [data, updateData] = useState([]);
useEffect(() => {
const [data, updateData] = useState<any>([]);
doSomethingCool(apiOptions).then(res => {
updateData(response.data);
})
}, [apiOptions]);
return {
data
};
};
Unfortunately it keeps running as the objects are not being recognised as being the same.
その理由の例は次の通りだと思います。
const objA = {
method: 'GET'
}
const objB = {
method: 'GET'
}
console.log(objA === objB)
ランニングはJSON.stringify(apiOptions)
効果があるのでしょうか?
ベストアンサー1
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
。