Skip to content

Commit

Permalink
feat: useLayoutEffect support firstMount param (#447)
Browse files Browse the repository at this point in the history
* refactor: useLayoutEffectSupport

* test: add test case
  • Loading branch information
zombieJ committed Jun 2, 2023
1 parent aa0cd87 commit 03d962c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
31 changes: 20 additions & 11 deletions src/hooks/useLayoutEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,39 @@ import canUseDom from '../Dom/canUseDom';
/**
* Wrap `React.useLayoutEffect` which will not throw warning message in test env
*/
const useLayoutEffect =
const useInternalLayoutEffect =
process.env.NODE_ENV !== 'test' && canUseDom()
? React.useLayoutEffect
: React.useEffect;

export default useLayoutEffect;

export const useLayoutUpdateEffect: typeof React.useEffect = (
callback,
deps,
const useLayoutEffect = (
callback: (mount: boolean) => void | VoidFunction,
deps?: React.DependencyList,
) => {
const firstMountRef = React.useRef(true);

useLayoutEffect(() => {
if (!firstMountRef.current) {
return callback();
}
useInternalLayoutEffect(() => {
return callback(firstMountRef.current);
}, deps);

// We tell react that first mount has passed
useLayoutEffect(() => {
useInternalLayoutEffect(() => {
firstMountRef.current = false;
return () => {
firstMountRef.current = true;
};
}, []);
};

export const useLayoutUpdateEffect: typeof React.useEffect = (
callback,
deps,
) => {
useLayoutEffect(firstMount => {
if (!firstMount) {
return callback();
}
}, deps);
};

export default useLayoutEffect;
24 changes: 24 additions & 0 deletions tests/hooks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,30 @@ describe('hooks', () => {
expect(errorSpy).not.toHaveBeenCalled();
errorSpy.mockRestore();
});

it('can get mount state', () => {
const Demo = () => {
const timesRef = React.useRef(0);
const [, forceUpdate] = React.useState(0);

useLayoutEffect(firstMount => {
if (timesRef.current === 0) {
expect(firstMount).toBeTruthy();
forceUpdate(1);
} else {
expect(firstMount).toBeFalsy();
forceUpdate(2);
}

timesRef.current += 1;
});

return <p>{timesRef.current}</p>;
};

const { container } = render(<Demo />);
expect(container.querySelector('p').textContent).toEqual('2');
});
});

describe('useState', () => {
Expand Down

1 comment on commit 03d962c

@vercel
Copy link

@vercel vercel bot commented on 03d962c Jun 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

util – ./

util.vercel.app
util-git-master-react-component.vercel.app
util-react-component.vercel.app

Please sign in to comment.