forked from Fieldscope/flux-hooks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
57 lines (41 loc) · 1.57 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import {
useEffect, useReducer, useMemo,
} from 'react';
import isEqual from 'lodash.isequal';
// useFluxStore combines useReducer and useEffect to use with FluxStores
// useReducer: Used to extract relevant values from the store
// useEffect is used to attach a listener to the store
export function useFluxStore(store, reducer, deps = [], strictEquality = false) {
// We use Lodash's isEqual check to make sure the state hasn't changed
// This can be expensive, but cheaper than a re-render
function reducerWithEqualityCheck(_p, _store) {
const refreshVal = reducer(_p, _store);
if (isEqual(refreshVal, _p)) return _p;
return refreshVal;
}
const [out, _dispatch] = useReducer(
strictEquality ? reducer : reducerWithEqualityCheck,
reducer(null, store),
);
// Watch dependencies, and dispatch if they change
useMemo(() => {
_dispatch(store);
}, deps);
useEffect(() => {
// Listener that is called when store is updated
function listener() {
// We dispatch the store to the reducer
_dispatch(store);
}
// Attach listener to store
const token = store.addListener(listener);
// This avoids potentially missing an update between useReducer --> render --> useEffect
_dispatch(store);
// On useEffect destruction, remove the listener
// Use arrow function otherwise EventEmitter blows up
return () => token.remove();
}, []);
// We make sure to pass [] so we're not attaching/detaching on every render
return out; // Reducer value gets returned to useFluxStore
}
export default useFluxStore;