Skip to content

Commit 961d2f5

Browse files
authored
Merge pull request #342 from notcodev/main
[fix]: useDidUpdate hook behavior with enabled strict mode
2 parents 3426fea + 1bfa781 commit 961d2f5

File tree

4 files changed

+46
-18
lines changed

4 files changed

+46
-18
lines changed

packages/core/src/bundle/hooks/useDidUpdate/useDidUpdate.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,21 @@ import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect/useIsomo
99
* @param {DependencyList} [deps] The dependencies list for the effect
1010
*
1111
* @example
12-
* useDidUpdate(() => console.log("effect runs on updates"), [deps]);
12+
* useDidUpdate(() => console.log("effect runs on updates"), deps);
1313
*/
1414
export const useDidUpdate = (effect, deps) => {
15-
const initialRender = useRef(true);
15+
const mounted = useRef(false);
16+
useIsomorphicLayoutEffect(
17+
() => () => {
18+
mounted.current = false;
19+
},
20+
[]
21+
);
1622
useIsomorphicLayoutEffect(() => {
17-
if (initialRender.current) {
18-
initialRender.current = false;
19-
return;
20-
}
21-
const effectReturns = effect();
22-
if (effectReturns && typeof effectReturns === 'function') {
23-
return effectReturns;
23+
if (mounted.current) {
24+
return effect();
2425
}
26+
mounted.current = true;
27+
return undefined;
2528
}, deps);
2629
};

packages/core/src/hooks/useDidUpdate/useDidUpdate.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { renderHook } from '@testing-library/react';
2+
import React from 'react';
23

34
import { useDidUpdate } from './useDidUpdate';
45

@@ -35,3 +36,15 @@ it('Should call effect on rerender when dependencies empty', () => {
3536
rerender();
3637
expect(effect).toHaveBeenCalledTimes(2);
3738
});
39+
40+
it('Should not call effect on initial render even in strict mode', () => {
41+
const effect = vi.fn();
42+
const { rerender } = renderHook(() => useDidUpdate(effect, []), {
43+
wrapper: React.StrictMode
44+
});
45+
46+
expect(effect).not.toHaveBeenCalled();
47+
48+
rerender();
49+
expect(effect).not.toHaveBeenCalled();
50+
});

packages/core/src/hooks/useDidUpdate/useDidUpdate.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,24 @@ import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect/useIsomo
1313
* @param {DependencyList} [deps] The dependencies list for the effect
1414
*
1515
* @example
16-
* useDidUpdate(() => console.log("effect runs on updates"), [deps]);
16+
* useDidUpdate(() => console.log("effect runs on updates"), deps);
1717
*/
1818
export const useDidUpdate = (effect: EffectCallback, deps?: DependencyList) => {
19-
const initialRender = useRef(true);
19+
const mounted = useRef(false);
20+
21+
useIsomorphicLayoutEffect(
22+
() => () => {
23+
mounted.current = false;
24+
},
25+
[]
26+
);
2027

2128
useIsomorphicLayoutEffect(() => {
22-
if (initialRender.current) {
23-
initialRender.current = false;
24-
return;
29+
if (mounted.current) {
30+
return effect();
2531
}
2632

27-
const effectReturns = effect();
28-
if (effectReturns && typeof effectReturns === 'function') {
29-
return effectReturns;
30-
}
33+
mounted.current = true;
34+
return undefined;
3135
}, deps);
3236
};

packages/core/src/hooks/useOnce/useOnce.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { renderHook } from '@testing-library/react';
2+
import React from 'react';
23

34
import { useOnce } from './useOnce';
45

@@ -9,6 +10,13 @@ it('Should use once', () => {
910
expect(callback).toHaveBeenCalled();
1011
});
1112

13+
it('Should use once even in strict mode', () => {
14+
const callback = vi.fn();
15+
renderHook(() => useOnce(callback), { wrapper: React.StrictMode });
16+
17+
expect(callback).toHaveBeenCalled();
18+
});
19+
1220
it('Should not call callback after rerender', () => {
1321
const callback = vi.fn();
1422
const { rerender } = renderHook(() => useOnce(callback));

0 commit comments

Comments
 (0)