Skip to content

Commit da1f51c

Browse files
authored
fix(useAsyncEffect): call cleanup when component unmounts before async effect resolves (#351)
1 parent fa3daa5 commit da1f51c

3 files changed

Lines changed: 29 additions & 0 deletions

File tree

.changeset/cool-spies-leave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'react-simplikit': patch
3+
---
4+
5+
fix(core/hooks): call cleanup when unmount occurs before async effect resolves

packages/core/src/hooks/useAsyncEffect/useAsyncEffect.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,25 @@ describe('useAsyncEffect', () => {
8989
expect(cleanup).toHaveBeenCalled();
9090
});
9191

92+
it('should call cleanup even when component unmounts before async effect resolves', async () => {
93+
const cleanup = vi.fn();
94+
const { unmount } = await renderHookSSR(() =>
95+
useAsyncEffect(async () => {
96+
await new Promise(resolve => setTimeout(resolve, 1000));
97+
return cleanup;
98+
}, [])
99+
);
100+
101+
await flushPromises();
102+
unmount();
103+
expect(cleanup).not.toHaveBeenCalled();
104+
105+
vi.advanceTimersByTime(1000);
106+
await flushPromises();
107+
108+
expect(cleanup).toHaveBeenCalledTimes(1);
109+
});
110+
92111
it('should call effect every rerender when deps are undefined', async () => {
93112
const effect = vi.fn().mockResolvedValue(undefined);
94113

packages/core/src/hooks/useAsyncEffect/useAsyncEffect.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ import { DependencyList, useEffect } from 'react';
2424
export function useAsyncEffect(effect: () => Promise<void | (() => void)>, deps?: DependencyList) {
2525
useEffect(() => {
2626
let cleanup: (() => void) | void;
27+
let isCleaned = false;
2728

2829
effect().then(result => {
2930
cleanup = result;
31+
if (isCleaned) {
32+
cleanup?.();
33+
}
3034
});
3135

3236
return () => {
37+
isCleaned = true;
3338
cleanup?.();
3439
};
3540

0 commit comments

Comments
 (0)