DEV Community

Discussion on: Cleaning up Async Functions in React's useEffect Hook (Unsubscribing)

Collapse
 
nokternol profile image
Mark Butterworth • Edited

I should start by saying I like the article and have yet to see anyone come up with an elegant solution to the problem. I agree that the closure variable is an anti-pattern and documented in the react teams blog as one of the most common. I solved this issue using signals.js to create an on-demand pub-sub which could be disconnected on unmount and personally I like the elegance of the execution path.

pseudo-code:
const useAsyncState = <TResult, TArgs>(promise: (...args: TArgs) => Promise<T>, cb: (v: T) => void): (...args: TArgs) => Promise<void> => {
const dispatcher = useMemo(() => new Signal<TResult>(), []);
useEffect(() => {
dispatcher.add(cb);
return () => dispatcher.clear();
}, [dispatcher, cb]);
return (...args: TArgs) => promise(...args).then(dispatcher.emit);
}

usage:
const [state, setState] = useState(undefined);
const loadData = useAsyncState(someAsyncMethod, setState);
useEffect(() => {
loadData();
}, [loadData]);

I wrote the code for an employer so cannot copy and paste it but above is the general idea/approach.
I actually like how the solution turned out and feel that it is clean albeit a little unintuitive as you then execute a Promise<void>

Collapse
 
elijahtrillionz profile image
Elijah Trillionz

Thanks for sharing.

Collapse
 
gnt profile image
gntsketches

Can you link to where the React team documents that the closure variable is an anti-pattern? Thanks!

Collapse
 
nokternol profile image
Mark Butterworth • Edited

reactjs.org/blog/2015/12/16/ismoun...

I should also clarify that I am not a fan of the cancellable promise approach either. IMO, the dispatcher pub/sub link in a hook is the cleanest implementation I've seen to date.

The link above is not actually referring to a closure variable but the general approach of tracking mounted to avoid the condition is the reason ismounted() was cited as being removed and it forming an antipattern.

Some comments have been hidden by the post's author - find out more