Skip to content

Commit

Permalink
feat: add useDeepCompareEffect hook
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich authored Apr 7, 2019
2 parents 5b39ab5 + ba9917c commit 77e015b
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
- [`useMount`](./docs/useMount.md) — calls `mount` callbacks.
- [`useUnmount`](./docs/useUnmount.md) — calls `unmount` callbacks.
- [`useUpdateEffect`](./docs/useUpdateEffect.md) — run an `effect` only on updates.
- [`useDeepCompareEffect`](./docs/useUpdateEffect.md) — run an `effect` depending on deep comparison of its dependencies
<br/>
<br/>
- [**State**](./docs/State.md)
Expand Down
30 changes: 30 additions & 0 deletions docs/useDeepCompareEffect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# `useDeepCompareEffect`

A modified useEffect hook that is using deep comparison on its dependencies instead of reference equality.

## Usage

```jsx
import {useCounter, useDeepCompareEffect} from 'react-use';

const Demo = () => {
const [count, {inc: inc}] = useCounter(0);
const options = { step: 2 };

useDeepCompareEffect(() => {
inc(options.step)
}, [options]);

return (
<div>
<p>useDeepCompareEffect: {count}</p>
</div>
);
};
```

## Reference

```ts
useDeepCompareEffect(effect: () => void | (() => void | undefined), deps: any[]);
```
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@
"homepage": "https://github.com/streamich/react-use#readme",
"dependencies": {
"nano-css": "^5.1.0",
"react-fast-compare": "^2.0.4",
"react-wait": "^0.3.0",
"screenfull": "^4.1.0",
"throttle-debounce": "^2.0.1",
"ts-easing": "^0.2.0"
},
"peerDependencies": {
"keyboardjs": "*",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"keyboardjs": "*",
"rebound": "*"
},
"devDependencies": {
Expand Down
33 changes: 33 additions & 0 deletions src/__stories__/useDeepCompareEffect.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {storiesOf} from '@storybook/react';
import * as React from 'react';
import {useCounter, useDeepCompareEffect} from '..';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
const [countNormal, {inc: incNormal}] = useCounter(0);
const [countDeep, {inc: incDeep}] = useCounter(0);
const options = {max: 500}

React.useEffect(() => {
if (countNormal < options.max) {
incNormal()
}
}, [options]);

useDeepCompareEffect(() => {
if (countNormal < options.max) {
incDeep()
}
}, [options]);

return (
<div>
<p>useEffect: {countNormal}</p>
<p>useDeepCompareEffect: {countDeep}</p>
</div>
);
};

storiesOf('useDeepCompareEffect', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useDeepCompareEffect.md')} />)
.add('Demo', () => <Demo/>)
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useDropArea from './useDropArea';
import useCounter from './useCounter';
import useCss from './useCss';
import useDebounce from './useDebounce';
import useDeepCompareEffect from './useDeepCompareEffect';
import useEffectOnce from './useEffectOnce';
import useEvent from './useEvent';
import useFavicon from './useFavicon';
Expand Down Expand Up @@ -78,6 +79,7 @@ export {
useCounter,
useCss,
useDebounce,
useDeepCompareEffect,
useEffectOnce,
useEvent,
useFavicon,
Expand Down
30 changes: 30 additions & 0 deletions src/useDeepCompareEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useRef, useEffect, EffectCallback, DependencyList } from 'react';
import * as isEqual from 'react-fast-compare';

const isPrimitive = (val: any) => val !== Object(val)

const useDeepCompareEffect = (effect: EffectCallback, deps: any[]) => {
if (process.env.NODE_ENV !== 'production') {
if (!deps || !deps.length) {
console.warn(
'`useDeepCompareEffect` should not be used with no dependencies. Use React.useEffect instead.'
);
}

if (deps.every(isPrimitive)) {
console.warn(
'`useDeepCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead.'
);
}
}

const ref = useRef<DependencyList | undefined>(undefined);

if (!isEqual(deps, ref.current)) {
ref.current = deps
}

useEffect(effect, ref.current)
}

export default useDeepCompareEffect
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9226,7 +9226,7 @@ react-error-overlay@^5.1.4:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.4.tgz#88dfb88857c18ceb3b9f95076f850d7121776991"
integrity sha512-fp+U98OMZcnduQ+NSEiQa4s/XMsbp+5KlydmkbESOw4P69iWZ68ZMFM5a2BuE0FgqPBKApJyRuYHR95jM8lAmg==

react-fast-compare@^2.0.2:
react-fast-compare@^2.0.2, react-fast-compare@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
Expand Down

0 comments on commit 77e015b

Please sign in to comment.