selectorFactory.js 3.5 KB

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