Reputation: 172
Currently, I am checking if the input
useEffect() hook dependency is at least a certain length before calling loadSearchData()
which is an async method that hits an API.
useEffect(() => {
if (input.length >= MIN_CHAR_INPUT) {
loadSearchData();
}
}, [input]);
Is there a way where I could move the input check to the input
dependency param for useEffect()? Probably a case where I need to write a custom hook.
Upvotes: 0
Views: 42
Reputation: 12637
Is there a way where I could move the input check to the input dependency param for useEffect()? Probably a case where I need to write a custom hook.
I'd build it this way:
function useEffect2(effect, deps, isValid = true) {
const cleanup = React.useRef(null);
useEffect(() => {
if (isValid) {
if (typeof cleanup.current === "function") {
// schedule cancellation of previous request right after effect has been called
// using the Promise construct here so I don't have to deal with a throwing cancellation function
Promise.resolve().then(cleanup.current);
}
// in case effect() throws,
// don't want to call the old cancellation function twice
cleanup.current = null;
// get new cancel-function
cleanup.current = effect();
}
}, deps);
useEffect(() => () => {
// deal with cancellation on unmount
typeof cleanup.current === "function" && cleanup.current();
}, []);
}
useEffect2(loadSearchData, [input], input.length >= MIN_CHAR_INPUT);
I just want to clarify the cancel. This will give us access to the current useEffect() call in the stack and allow us to properly handle the call without any memory-leaks
From https://reactjs.org/docs/hooks-effect.html#recap
We’ve learned that useEffect lets us express different kinds of side effects after a component renders. Some effects might require cleanup so they return a function
Cleanup is probably a better name. I use it the most to "cancel" previous ajax-requests if they are still pending/prevent them to update the state. I've renamed the variable in the code.
What we're trying to emulate here is a useEffect
that runs the effect conditionally. So when the condition is false, we don't want the effect to cleanup the previous call; as if the deps
didn't change. Therefore we need to handle the cleanup function ourselves, and when/wether it should be invoked. That's
componentWillUnmount
That's what this ref
is for. Since the reference is overwritten with every call to effect
this shouldn't leak any memory.
Upvotes: 1