Skip to content

Commit

Permalink
feat: add usePrevious hook
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich authored May 7, 2019
2 parents 62d6254 + dd5c1ef commit 4861a39
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@
- [`createMemo`](./docs/createMemo.md) — factory of memoized hooks.
- [`useGetSet`](./docs/useGetSet.md) — returns state getter `get()` instead of raw state.
- [`useGetSetState`](./docs/useGetSetState.md) — as if [`useGetSet`](./docs/useGetSet.md) and [`useSetState`](./docs/useSetState.md) had a baby.
- [`usePrevious`](./docs/usePrevious.md) — returns the previous state or props.

- [`useObservable`](./docs/useObservable.md) — tracks latest value of an `Observable`.
- [`useSetState`](./docs/useSetState.md) — creates `setState` method which works like `this.setState`. [![][img-demo]](https://codesandbox.io/s/n75zqn1xp0)
- [`useToggle` and `useBoolean`](./docs/useToggle.md) — tracks state of a boolean.
Expand Down
26 changes: 26 additions & 0 deletions docs/usePrevious.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# `usePrevious`

React state hook that returns the previous state as described in the [React hooks FAQ](https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state).

## Usage

```jsx
import {usePrevious} from 'react-use';

const Demo = () => {
const [count, setCount] = React.useState(0);
const prevCount = usePrevious(count);

return (
<p>
Now: {count}, before: {prevCount}
</p>
);
};
```

## Reference

```ts
const prevState = usePrevious = <T>(state: T): T;
```
23 changes: 23 additions & 0 deletions src/__stories__/usePrevious.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { usePrevious } from '..';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
const [count, setCount] = React.useState(0);
const prevCount = usePrevious(count);

return (
<div>
<p>
Now: {count}, before: {String(prevCount)}
</p>
<button onClick={() => setCount(value => value + 1)}>+</button>
<button onClick={() => setCount(value => value - 1)}>-</button>
</div>
);
};

storiesOf('State|usePrevious', module)
.add('Docs', () => <ShowDocs md={require('../../docs/usePrevious.md')} />)
.add('Demo', () => <Demo />);
22 changes: 22 additions & 0 deletions src/__tests__/usePrevious.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { cleanup, renderHook } from 'react-hooks-testing-library';
import usePrevious from '../usePrevious';

afterEach(cleanup);

describe('usePrevious', () => {
it('should be defined', () => {
expect(usePrevious).toBeDefined();
});

const hook = renderHook(props => usePrevious(props), { initialProps: 0 });

it('should return undefined on initial render', () => {
expect(hook.result.current).toBe(undefined);
});

it('should return previous state after update', () => {
hook.rerender(1);
hook.rerender(2);
expect(hook.result.current).toBe(1);
});
});
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import useNumber from './useNumber';
import useObservable from './useObservable';
import useOrientation from './useOrientation';
import usePageLeave from './usePageLeave';
import usePrevious from './usePrevious';
import usePromise from './usePromise';
import useRaf from './useRaf';
import useRefMounted from './useRefMounted';
Expand Down Expand Up @@ -119,6 +120,7 @@ export {
useObservable,
useOrientation,
usePageLeave,
usePrevious,
usePromise,
useRaf,
useRefMounted,
Expand Down
13 changes: 13 additions & 0 deletions src/usePrevious.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useEffect, useRef } from 'react';

const usePrevious = <T>(state: T): T | undefined => {
const ref = useRef<T>();

useEffect(() => {
ref.current = state;
});

return ref.current;
};

export default usePrevious;

0 comments on commit 4861a39

Please sign in to comment.