Skip to content

Commit 03d962c

Browse files
authored
feat: useLayoutEffect support firstMount param (#447)
* refactor: useLayoutEffectSupport * test: add test case
1 parent aa0cd87 commit 03d962c

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

src/hooks/useLayoutEffect.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,39 @@ import canUseDom from '../Dom/canUseDom';
44
/**
55
* Wrap `React.useLayoutEffect` which will not throw warning message in test env
66
*/
7-
const useLayoutEffect =
7+
const useInternalLayoutEffect =
88
process.env.NODE_ENV !== 'test' && canUseDom()
99
? React.useLayoutEffect
1010
: React.useEffect;
1111

12-
export default useLayoutEffect;
13-
14-
export const useLayoutUpdateEffect: typeof React.useEffect = (
15-
callback,
16-
deps,
12+
const useLayoutEffect = (
13+
callback: (mount: boolean) => void | VoidFunction,
14+
deps?: React.DependencyList,
1715
) => {
1816
const firstMountRef = React.useRef(true);
1917

20-
useLayoutEffect(() => {
21-
if (!firstMountRef.current) {
22-
return callback();
23-
}
18+
useInternalLayoutEffect(() => {
19+
return callback(firstMountRef.current);
2420
}, deps);
2521

2622
// We tell react that first mount has passed
27-
useLayoutEffect(() => {
23+
useInternalLayoutEffect(() => {
2824
firstMountRef.current = false;
2925
return () => {
3026
firstMountRef.current = true;
3127
};
3228
}, []);
3329
};
30+
31+
export const useLayoutUpdateEffect: typeof React.useEffect = (
32+
callback,
33+
deps,
34+
) => {
35+
useLayoutEffect(firstMount => {
36+
if (!firstMount) {
37+
return callback();
38+
}
39+
}, deps);
40+
};
41+
42+
export default useLayoutEffect;

tests/hooks.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,30 @@ describe('hooks', () => {
343343
expect(errorSpy).not.toHaveBeenCalled();
344344
errorSpy.mockRestore();
345345
});
346+
347+
it('can get mount state', () => {
348+
const Demo = () => {
349+
const timesRef = React.useRef(0);
350+
const [, forceUpdate] = React.useState(0);
351+
352+
useLayoutEffect(firstMount => {
353+
if (timesRef.current === 0) {
354+
expect(firstMount).toBeTruthy();
355+
forceUpdate(1);
356+
} else {
357+
expect(firstMount).toBeFalsy();
358+
forceUpdate(2);
359+
}
360+
361+
timesRef.current += 1;
362+
});
363+
364+
return <p>{timesRef.current}</p>;
365+
};
366+
367+
const { container } = render(<Demo />);
368+
expect(container.querySelector('p').textContent).toEqual('2');
369+
});
346370
});
347371

348372
describe('useState', () => {

0 commit comments

Comments
 (0)