Skip to content

Commit

Permalink
feat: implement useMountEffect and useUnmountEffect hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
xobotyi committed Apr 15, 2021
1 parent eea1b36 commit 98ec434
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/useFirstMountState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useEffect, useRef } from 'react';

/**
* Returns boolean that is `true` only on first render
*/
export function useFirstMountState(): boolean {
const isFirstMount = useRef(true);

Expand Down
13 changes: 13 additions & 0 deletions src/useMountEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useEffect } from 'react';

/**
* Run effect only when component is first mounted.
*
* @param fn effector to run on nmount
*/
export function useMountEffect(fn: () => void): void {
useEffect(() => {
fn();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}
16 changes: 16 additions & 0 deletions src/useUnmountEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useEffect } from 'react';

/**
* Run effect only when component is unmounted.
*
* @param fn effector to run on unmount
*/
export function useUnmountEffect(fn: () => void): void {
useEffect(
() => () => {
fn();
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
}
24 changes: 24 additions & 0 deletions tests/dom/useMountEffect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { renderHook } from '@testing-library/react-hooks/dom';
import { useMountEffect } from '../../src/useMountEffect';

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

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

expect(result.current).toBe(undefined);
expect(spy).toHaveBeenCalledTimes(1);

rerender();
rerender();
rerender();
rerender();

expect(spy).toHaveBeenCalledTimes(1);

unmount();

expect(spy).toHaveBeenCalledTimes(1);
});
});
24 changes: 24 additions & 0 deletions tests/dom/useUnmountEffect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { renderHook } from '@testing-library/react-hooks/dom';
import { useUnmountEffect } from '../../src/useUnmountEffect';

describe('useUnmountEffect', () => {
it('should call effector only when component unmounted', () => {
const spy = jest.fn();

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

expect(result.current).toBe(undefined);
expect(spy).toHaveBeenCalledTimes(0);

rerender();
rerender();
rerender();
rerender();

expect(spy).toHaveBeenCalledTimes(0);

unmount();

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

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

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

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

describe('useUnmountEffect', () => {
it('should call effector only when component unmounted', () => {
const spy = jest.fn();

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

expect(result.current).toBe(undefined);
expect(spy).toHaveBeenCalledTimes(0);
});
});

0 comments on commit 98ec434

Please sign in to comment.