Skip to content

Commit

Permalink
feat: useUpdateEffect hook
Browse files Browse the repository at this point in the history
  • Loading branch information
xobotyi committed Apr 16, 2021
1 parent 86dc3cc commit bc3a655
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 4 deletions.
14 changes: 14 additions & 0 deletions src/useUpdateEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { DependencyList, EffectCallback, useEffect } from 'react';
import { useFirstMountState } from './useFirstMountState';

export function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void {
const isFirstMount = useFirstMountState();

// eslint-disable-next-line consistent-return
useEffect(() => {
if (!isFirstMount) {
return effect();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
}
43 changes: 43 additions & 0 deletions tests/dom/useUpdateEffect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { renderHook } from '@testing-library/react-hooks/dom';
import { useUpdateEffect } from '../../src/useUpdateEffect';

describe('useUpdateEffect', () => {
it('should call effector only on updates (after first render)', () => {
const spy = jest.fn();

const { rerender, unmount } = renderHook(() => useUpdateEffect(spy));

expect(spy).toHaveBeenCalledTimes(0);

rerender();
expect(spy).toHaveBeenCalledTimes(1);

rerender();
expect(spy).toHaveBeenCalledTimes(2);

unmount();
expect(spy).toHaveBeenCalledTimes(2);
});

it('should accept dependencies as useEffect', () => {
const spy = jest.fn();

const { rerender, unmount } = renderHook(({ deps }) => useUpdateEffect(spy, deps), {
initialProps: { deps: [1, 2, 3] },
});

expect(spy).toHaveBeenCalledTimes(0);

rerender();
expect(spy).toHaveBeenCalledTimes(0);

rerender({ deps: [1, 2, 4] });
expect(spy).toHaveBeenCalledTimes(1);

rerender({ deps: [1, 2, 4] });
expect(spy).toHaveBeenCalledTimes(1);

unmount();
expect(spy).toHaveBeenCalledTimes(1);
});
});
3 changes: 1 addition & 2 deletions tests/ssr/useMountEffect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ describe('useMountEffect', () => {
it('should call effector only on first render', () => {
const spy = jest.fn();

const { result } = renderHook(() => useMountEffect(spy));
renderHook(() => useMountEffect(spy));

expect(result.current).toBe(undefined);
expect(spy).toHaveBeenCalledTimes(0);
});
});
3 changes: 1 addition & 2 deletions tests/ssr/useUnmountEffect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ describe('useUnmountEffect', () => {
it('should call effector only when component unmounted', () => {
const spy = jest.fn();

const { result } = renderHook(() => useUnmountEffect(spy));
renderHook(() => useUnmountEffect(spy));

expect(result.current).toBe(undefined);
expect(spy).toHaveBeenCalledTimes(0);
});
});
12 changes: 12 additions & 0 deletions tests/ssr/useUpdateEffect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { renderHook } from '@testing-library/react-hooks/server';
import { useUpdateEffect } from '../../src/useUpdateEffect';

describe('useUpdateEffect', () => {
it('should not call effector on mount', () => {
const spy = jest.fn();

renderHook(() => useUpdateEffect(spy));

expect(spy).toHaveBeenCalledTimes(0);
});
});

0 comments on commit bc3a655

Please sign in to comment.