summaryrefslogtreecommitdiff
path: root/src/misc/store.js
blob: 0893715a23dcedea56ee172994174ca4a9c9180d (plain)
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 React, {
  createContext,
  useState,
  useEffect,
  useContext,
  useMemo
} from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import shallowEqual from './shallowEqual';

const StoreContext = createContext(null);

export function Provider({ store, children }) {
  return (
    <StoreContext.Provider value={store}>{children}</StoreContext.Provider>
  );
}

Provider.propTypes = {
  store: PropTypes.object,
  children: PropTypes.node
};

export function useStore() {
  // return the context
  // which is the redux store
  return useContext(StoreContext);
}

function bindActions(actions, dispatch) {
  const a = typeof actions === 'function' ? actions() : actions;
  return bindActionCreators(a, dispatch);
}

export function useActions(actions) {
  const { dispatch } = useStore();
  return useMemo(() => bindActions(actions, dispatch), [actions, dispatch]);
}

export function useStoreState(selector) {
  const store = useStore();
  const initialMappedState = selector(store.getState());
  const [compState, setCompState] = useState(initialMappedState);
  // subscribe to store change
  useEffect(() => {
    let compStateCurr = compState;
    return store.subscribe(() => {
      const compStateNext = selector(store.getState());
      if (shallowEqual(compStateCurr, compStateNext)) return;
      // update state if not equal
      compStateCurr = compStateNext;
      setCompState(compStateNext);
    });
  }, [compState, selector, store]);
  return compState;
}