selectorFactory.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
  2. const _excluded = ["initMapStateToProps", "initMapDispatchToProps", "initMergeProps"];
  3. import verifySubselectors from './verifySubselectors';
  4. export function pureFinalPropsSelectorFactory(mapStateToProps, mapDispatchToProps, mergeProps, dispatch, {
  5. areStatesEqual,
  6. areOwnPropsEqual,
  7. areStatePropsEqual
  8. }) {
  9. let hasRunAtLeastOnce = false;
  10. let state;
  11. let ownProps;
  12. let stateProps;
  13. let dispatchProps;
  14. let mergedProps;
  15. function handleFirstCall(firstState, firstOwnProps) {
  16. state = firstState;
  17. ownProps = firstOwnProps;
  18. stateProps = mapStateToProps(state, ownProps);
  19. dispatchProps = mapDispatchToProps(dispatch, ownProps);
  20. mergedProps = mergeProps(stateProps, dispatchProps, ownProps);
  21. hasRunAtLeastOnce = true;
  22. return mergedProps;
  23. }
  24. function handleNewPropsAndNewState() {
  25. stateProps = mapStateToProps(state, ownProps);
  26. if (mapDispatchToProps.dependsOnOwnProps) dispatchProps = mapDispatchToProps(dispatch, ownProps);
  27. mergedProps = mergeProps(stateProps, dispatchProps, ownProps);
  28. return mergedProps;
  29. }
  30. function handleNewProps() {
  31. if (mapStateToProps.dependsOnOwnProps) stateProps = mapStateToProps(state, ownProps);
  32. if (mapDispatchToProps.dependsOnOwnProps) dispatchProps = mapDispatchToProps(dispatch, ownProps);
  33. mergedProps = mergeProps(stateProps, dispatchProps, ownProps);
  34. return mergedProps;
  35. }
  36. function handleNewState() {
  37. const nextStateProps = mapStateToProps(state, ownProps);
  38. const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps);
  39. stateProps = nextStateProps;
  40. if (statePropsChanged) mergedProps = mergeProps(stateProps, dispatchProps, ownProps);
  41. return mergedProps;
  42. }
  43. function handleSubsequentCalls(nextState, nextOwnProps) {
  44. const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps);
  45. const stateChanged = !areStatesEqual(nextState, state, nextOwnProps, ownProps);
  46. state = nextState;
  47. ownProps = nextOwnProps;
  48. if (propsChanged && stateChanged) return handleNewPropsAndNewState();
  49. if (propsChanged) return handleNewProps();
  50. if (stateChanged) return handleNewState();
  51. return mergedProps;
  52. }
  53. return function pureFinalPropsSelector(nextState, nextOwnProps) {
  54. return hasRunAtLeastOnce ? handleSubsequentCalls(nextState, nextOwnProps) : handleFirstCall(nextState, nextOwnProps);
  55. };
  56. }
  57. // TODO: Add more comments
  58. // The selector returned by selectorFactory will memoize its results,
  59. // allowing connect's shouldComponentUpdate to return false if final
  60. // props have not changed.
  61. export default function finalPropsSelectorFactory(dispatch, _ref) {
  62. let {
  63. initMapStateToProps,
  64. initMapDispatchToProps,
  65. initMergeProps
  66. } = _ref,
  67. options = _objectWithoutPropertiesLoose(_ref, _excluded);
  68. const mapStateToProps = initMapStateToProps(dispatch, options);
  69. const mapDispatchToProps = initMapDispatchToProps(dispatch, options);
  70. const mergeProps = initMergeProps(dispatch, options);
  71. if (process.env.NODE_ENV !== 'production') {
  72. verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps);
  73. }
  74. return pureFinalPropsSelectorFactory(mapStateToProps, mapDispatchToProps, mergeProps, dispatch, options);
  75. }