Skip to content

Commit d85f860

Browse files
feat(hooks): add useDeepEqualEffect and useShallowEqualEffect
1 parent 19ccbee commit d85f860

File tree

7 files changed

+4616
-4827
lines changed

7 files changed

+4616
-4827
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ Visit [storybook](https://beizhedenglong.github.io/react-hooks-lib)
2222
| [`createContextState`](#createContextStateInitial) | initial | { ContextProvider, ContextConsumer, set, useContextState } |
2323
| [`createGlobalState`](#createGlobalStateInitial) | initial | { GlobalProvider, GlobalConsumer, set, useGlobalState } |
2424
| [`useMergeState`](#usemergestateinitial) | initial | { state, set } |
25-
| [`useStateCallback`](#useStateCallbackInitial-f) | initial, f | { state, set } |
25+
| [`useStateCallback`](#useStateCallbackInitial-f) | initial, f | { state, set } |
2626
| [`useUndo`](#useUndoInitial) | initial | { past, present, future, set, undo, redo } |
2727
| [`useCounter`](#useCounterInitial) | initial | { count, set, reset, inc, dec } |
2828
| [`useToggle`](#useToggleInitial) | initial | { on, set, reset, toggle } |
2929
| [`useList`](#useListInitial) | initial | { list, set, reset, push, sort, filter } |
3030
| [`useMap`](#useMapInitial) | initial | { values, set, reset, clear, get, has, del } |
31+
| <h6>Effect</h6> | | |
32+
| `useShallowEqualEffect` | f, deps | - |
33+
| `useDeepEqualEffect` | f, deps | - |
3134
| <h6>Network</h6> | | |
3235
| [`useFetch`](#useFetchInitialUrl-initialOptions-onMount) | initialUrl, initialOptions, config | { loading, data, error, fetch, setUrl, setOptions, setData } |
3336
| [`useOnlineStatus`](#useonlinestatus) | | |

__tests__/effect.test.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import 'react-testing-library/cleanup-after-each'
2+
import React, { useEffect } from 'react'
3+
import {
4+
render, fireEvent,
5+
} from 'react-testing-library'
6+
import {
7+
useCounter, useDeepEqualEffect, useShallowEqualEffect,
8+
} from '../src/index'
9+
10+
const fn = jest.fn()
11+
const shallowFn = jest.fn()
12+
const shallowFn2 = jest.fn()
13+
const deepFn = jest.fn()
14+
jest.useFakeTimers()
15+
16+
17+
const Example = () => {
18+
const { inc } = useCounter(0)
19+
useEffect(fn, [{ name: 'victor' }])
20+
useShallowEqualEffect(shallowFn, [{ name: 'victor' }])
21+
useShallowEqualEffect(shallowFn2, [{ a: { b: 1 } }])
22+
useDeepEqualEffect(deepFn, [{ a: { b: 1 } }])
23+
return (
24+
<div>
25+
<button onClick={() => inc(1)}>+1</button>
26+
</div>
27+
)
28+
}
29+
const { getByText } = render(<Example />)
30+
31+
test('effect', async () => {
32+
jest.runAllTimers()
33+
expect(fn).toBeCalledTimes(1)
34+
expect(shallowFn).toBeCalledTimes(1)
35+
expect(shallowFn2).toBeCalledTimes(1)
36+
expect(deepFn).toBeCalledTimes(1)
37+
38+
fireEvent.click(getByText('+1'))
39+
fireEvent.click(getByText('+1'))
40+
jest.runAllTimers()
41+
expect(fn).toBeCalledTimes(3)
42+
expect(shallowFn).toBeCalledTimes(1)
43+
expect(shallowFn2).toBeCalledTimes(3)
44+
expect(deepFn).toBeCalledTimes(1)
45+
})

package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"dev": "microbundle watch -o dist/ --sourcemap false --no-compress",
1212
"test": "jest --coverage --config=jest.config.js",
1313
"report-coverage": "cat ./coverage/lcov.info | coveralls",
14-
"storybook": "start-storybook -p 6006",
14+
"storybook": "start-storybook -p 6006 --ci",
1515
"build-storybook": "build-storybook",
1616
"deploy-storybook": "storybook-to-ghpages",
1717
"semantic-release": "semantic-release"
@@ -23,7 +23,8 @@
2323
},
2424
"husky": {
2525
"hooks": {
26-
"pre-push": "yarn test"
26+
"pre-push": "yarn test",
27+
"prepare-commit-msg": "exec < /dev/tty && git cz --hook || true"
2728
}
2829
},
2930
"keywords": [
@@ -78,7 +79,10 @@
7879
"peerDependencies": {
7980
"react": "^16.8.0"
8081
},
81-
"dependencies": {},
82+
"dependencies": {
83+
"lodash.isequal": "^4.5.0",
84+
"shallowequal": "^1.1.0"
85+
},
8286
"repository": {
8387
"type": "git",
8488
"url": "https://github.com/beizhedenglong/react-hooks-lib.git"

src/hooks/useEqualEffect.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useEffect, useRef } from 'react'
2+
import shallowEqual from 'shallowequal'
3+
import deepEqual from 'lodash.isequal'
4+
5+
const isShallowEqual = (depsA = [], depsB = []) => {
6+
if (depsA.length !== depsB.length) {
7+
return false
8+
}
9+
return depsA.every((a, index) => shallowEqual(a, depsB[index]))
10+
}
11+
12+
const useEqualEffect = (compareFn, f, deps) => {
13+
const ref = useRef([])
14+
if (!compareFn(ref.current, deps)) {
15+
ref.current = deps
16+
}
17+
useEffect(f, ref.current)
18+
}
19+
20+
export const useShallowEqualEffect = (f, deps) => {
21+
useEqualEffect(isShallowEqual, f, deps)
22+
}
23+
24+
export const useDeepEqualEffect = (f, deps) => {
25+
useEqualEffect(deepEqual, f, deps)
26+
}

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ export { default as createGlobalState, createContextState } from './hooks/useGlo
3333
export { default as useUndo } from './hooks/useUndo'
3434

3535
export { default as useStateCallback } from './hooks/useStateCallback'
36+
37+
export { useShallowEqualEffect, useDeepEqualEffect } from './hooks/useEqualEffect'

stories/effect.stories.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { storiesOf } from '@storybook/react'
2+
3+
const section = name => `Effect|${name}`
4+
5+
storiesOf(section('useDeepEqualEffect & useShallowEqualEffect'), module)
6+
.addLiveSource('demo', `
7+
const Example = () => {
8+
const { count, inc } = useCounter(0)
9+
React.useEffect(() => {
10+
// will be called on every render
11+
console.log("useEffect")
12+
}, [{ name: 'victor' }])
13+
14+
useShallowEqualEffect(() => {
15+
// only be called on first render
16+
console.log("useShallowEqualEffect1")
17+
}, [{ name: 'victor' }])
18+
19+
useShallowEqualEffect(() => {
20+
// will be called on every render
21+
console.log("useShallowEqualEffect2")
22+
}, [{ a: { b: 1 } }])
23+
24+
useDeepEqualEffect(() => {
25+
// only be called on first render
26+
console.log("useDeepEqualEffect")
27+
}, [{ a: { b: 1 } }])
28+
return (
29+
<div>
30+
count: {count}
31+
<button onClick={() => inc(1)}>+1</button>
32+
</div>
33+
)
34+
}
35+
return <Example />
36+
`)

0 commit comments

Comments
 (0)