say I have a function like this:
export const usePagedGetAll = <R, Args extends any[]>(
baseUrl: string,
...args: Args
) => {
const fn = useWrappedRemoteCall(
async () => {
return await fetchRequest<RemoteData<R>>(url, options);
}
);
useEffect(() => {
(async () => {
await fn.execute(...args);
})();
}, [args, fn, paginationInfo.skip, paginationInfo.take]);
return fn
};
The problem is that args is a new array each time so infinite re-render happens if it is in the deps array. I do want it to re-render if an element changes.
same goes for the fn function, it is new each time so it will cause infinite re-render, what can I do.
I could stop the hooks eslint rule applying the fix
useEffect(() => {
(async () => {
await fn.execute(...args);
})();
// eslint-disable-next-line
}, [paginationInfo.skip, paginationInfo.take]);
but this seems like a common problem
According to your needs, I divide the dependency into two parts for analysis.
args is an array and will be brand new each time.
Consider creating a useCustorCompareEffect. By customizing the comparison function. The effect will actually be triggered only when the specified value changes.
const useCustorCompareEffect = (callback, value, compare) => {
const prev = useRef({ init: true, value })
useEffect(() => {
const { current } = prev
if (current.init) {
callback()
current.init = false
} else {
if (!compare || !compare(value, current.value)) {
callback()
current.value = value
}
}
}, [callback, value, compare])
}
const useDemo=()=>{
const compare = useCallback((curr, prev) => {
// Compare functions, return comparison results, use `useCallback` to prevent triggering `effect` due to compare
}, [])
useCustorCompareEffect(
() => {
...
},
[data],
compare,
)
}
To use a function as a dependency, you can wrap the function definition in useCallback and then define the dependencies required by this function in useCallback.
const execute = useCallback(() => {
console.log('update')
}, [])
useEffect(() => {
execute()
}, [execute);
In your case, your function is obtained by another useWrappedRemoteCall, which needs to use the useCallback package execute definition in useWrappedRemoteCall and then return.
In addition, if you only use execute in useEffect, you need to extract execute and then use execute as a dependency. To prevent other data changes in fn from triggering effect
const useWrappedRemoteCall = () => {
const execute = useCallback(() => {
console.log('update')
}, [])
return { execute }
}
const usePagedGetAll = () => {
const { execute } = useWrappedRemoteCall()
useEffect(() => {
execute()
}, [execute])
}
If there are other special circumstances, please let me know.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With