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