You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					438 lines
				
				21 KiB
			
		
		
			
		
	
	
					438 lines
				
				21 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.__esModule = true;
							 | 
						||
| 
								 | 
							
								exports.default = exports.initializeConnect = void 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _hoistNonReactStatics = _interopRequireDefault(require("hoist-non-react-statics"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _react = _interopRequireWildcard(require("react"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _reactIs = require("react-is");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _selectorFactory = _interopRequireDefault(require("../connect/selectorFactory"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _mapDispatchToProps = require("../connect/mapDispatchToProps");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _mapStateToProps = require("../connect/mapStateToProps");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _mergeProps = require("../connect/mergeProps");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _Subscription = require("../utils/Subscription");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _useIsomorphicLayoutEffect = require("../utils/useIsomorphicLayoutEffect");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _shallowEqual = _interopRequireDefault(require("../utils/shallowEqual"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _warning = _interopRequireDefault(require("../utils/warning"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _Context = require("./Context");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _useSyncExternalStore = require("../utils/useSyncExternalStore");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const _excluded = ["reactReduxForwardedRef"];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let useSyncExternalStore = _useSyncExternalStore.notInitialized;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const initializeConnect = fn => {
							 | 
						||
| 
								 | 
							
								  useSyncExternalStore = fn;
							 | 
						||
| 
								 | 
							
								}; // Define some constant arrays just to avoid re-creating these
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.initializeConnect = initializeConnect;
							 | 
						||
| 
								 | 
							
								const EMPTY_ARRAY = [null, 0];
							 | 
						||
| 
								 | 
							
								const NO_SUBSCRIPTION_ARRAY = [null, null]; // Attempts to stringify whatever not-really-a-component value we were given
							 | 
						||
| 
								 | 
							
								// for logging in an error message
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const stringifyComponent = Comp => {
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    return JSON.stringify(Comp);
							 | 
						||
| 
								 | 
							
								  } catch (err) {
							 | 
						||
| 
								 | 
							
								    return String(Comp);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This is "just" a `useLayoutEffect`, but with two modifications:
							 | 
						||
| 
								 | 
							
								// - we need to fall back to `useEffect` in SSR to avoid annoying warnings
							 | 
						||
| 
								 | 
							
								// - we extract this to a separate function to avoid closing over values
							 | 
						||
| 
								 | 
							
								//   and causing memory leaks
							 | 
						||
| 
								 | 
							
								function useIsomorphicLayoutEffectWithArgs(effectFunc, effectArgs, dependencies) {
							 | 
						||
| 
								 | 
							
								  (0, _useIsomorphicLayoutEffect.useIsomorphicLayoutEffect)(() => effectFunc(...effectArgs), dependencies);
							 | 
						||
| 
								 | 
							
								} // Effect callback, extracted: assign the latest props values to refs for later usage
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function captureWrapperProps(lastWrapperProps, lastChildProps, renderIsScheduled, wrapperProps, // actualChildProps: unknown,
							 | 
						||
| 
								 | 
							
								childPropsFromStoreUpdate, notifyNestedSubs) {
							 | 
						||
| 
								 | 
							
								  // We want to capture the wrapper props and child props we used for later comparisons
							 | 
						||
| 
								 | 
							
								  lastWrapperProps.current = wrapperProps;
							 | 
						||
| 
								 | 
							
								  renderIsScheduled.current = false; // If the render was from a store update, clear out that reference and cascade the subscriber update
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (childPropsFromStoreUpdate.current) {
							 | 
						||
| 
								 | 
							
								    childPropsFromStoreUpdate.current = null;
							 | 
						||
| 
								 | 
							
								    notifyNestedSubs();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								} // Effect callback, extracted: subscribe to the Redux store or nearest connected ancestor,
							 | 
						||
| 
								 | 
							
								// check for updates after dispatched actions, and trigger re-renders.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function subscribeUpdates(shouldHandleStateChanges, store, subscription, childPropsSelector, lastWrapperProps, lastChildProps, renderIsScheduled, isMounted, childPropsFromStoreUpdate, notifyNestedSubs, // forceComponentUpdateDispatch: React.Dispatch<any>,
							 | 
						||
| 
								 | 
							
								additionalSubscribeListener) {
							 | 
						||
| 
								 | 
							
								  // If we're not subscribed to the store, nothing to do here
							 | 
						||
| 
								 | 
							
								  if (!shouldHandleStateChanges) return () => {}; // Capture values for checking if and when this component unmounts
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let didUnsubscribe = false;
							 | 
						||
| 
								 | 
							
								  let lastThrownError = null; // We'll run this callback every time a store subscription update propagates to this component
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const checkForUpdates = () => {
							 | 
						||
| 
								 | 
							
								    if (didUnsubscribe || !isMounted.current) {
							 | 
						||
| 
								 | 
							
								      // Don't run stale listeners.
							 | 
						||
| 
								 | 
							
								      // Redux doesn't guarantee unsubscriptions happen until next dispatch.
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    } // TODO We're currently calling getState ourselves here, rather than letting `uSES` do it
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const latestStoreState = store.getState();
							 | 
						||
| 
								 | 
							
								    let newChildProps, error;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      // Actually run the selector with the most recent store state and wrapper props
							 | 
						||
| 
								 | 
							
								      // to determine what the child props should be
							 | 
						||
| 
								 | 
							
								      newChildProps = childPropsSelector(latestStoreState, lastWrapperProps.current);
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      error = e;
							 | 
						||
| 
								 | 
							
								      lastThrownError = e;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!error) {
							 | 
						||
| 
								 | 
							
								      lastThrownError = null;
							 | 
						||
| 
								 | 
							
								    } // If the child props haven't changed, nothing to do here - cascade the subscription update
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (newChildProps === lastChildProps.current) {
							 | 
						||
| 
								 | 
							
								      if (!renderIsScheduled.current) {
							 | 
						||
| 
								 | 
							
								        notifyNestedSubs();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      // Save references to the new child props.  Note that we track the "child props from store update"
							 | 
						||
| 
								 | 
							
								      // as a ref instead of a useState/useReducer because we need a way to determine if that value has
							 | 
						||
| 
								 | 
							
								      // been processed.  If this went into useState/useReducer, we couldn't clear out the value without
							 | 
						||
| 
								 | 
							
								      // forcing another re-render, which we don't want.
							 | 
						||
| 
								 | 
							
								      lastChildProps.current = newChildProps;
							 | 
						||
| 
								 | 
							
								      childPropsFromStoreUpdate.current = newChildProps;
							 | 
						||
| 
								 | 
							
								      renderIsScheduled.current = true; // TODO This is hacky and not how `uSES` is meant to be used
							 | 
						||
| 
								 | 
							
								      // Trigger the React `useSyncExternalStore` subscriber
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      additionalSubscribeListener();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }; // Actually subscribe to the nearest connected ancestor (or store)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  subscription.onStateChange = checkForUpdates;
							 | 
						||
| 
								 | 
							
								  subscription.trySubscribe(); // Pull data from the store after first render in case the store has
							 | 
						||
| 
								 | 
							
								  // changed since we began.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  checkForUpdates();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const unsubscribeWrapper = () => {
							 | 
						||
| 
								 | 
							
								    didUnsubscribe = true;
							 | 
						||
| 
								 | 
							
								    subscription.tryUnsubscribe();
							 | 
						||
| 
								 | 
							
								    subscription.onStateChange = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (lastThrownError) {
							 | 
						||
| 
								 | 
							
								      // It's possible that we caught an error due to a bad mapState function, but the
							 | 
						||
| 
								 | 
							
								      // parent re-rendered without this component and we're about to unmount.
							 | 
						||
| 
								 | 
							
								      // This shouldn't happen as long as we do top-down subscriptions correctly, but
							 | 
						||
| 
								 | 
							
								      // if we ever do those wrong, this throw will surface the error in our tests.
							 | 
						||
| 
								 | 
							
								      // In that case, throw the error from here so it doesn't get lost.
							 | 
						||
| 
								 | 
							
								      throw lastThrownError;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return unsubscribeWrapper;
							 | 
						||
| 
								 | 
							
								} // Reducer initial state creation for our update reducer
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const initStateUpdates = () => EMPTY_ARRAY;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function strictEqual(a, b) {
							 | 
						||
| 
								 | 
							
								  return a === b;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Infers the type of props that a connector will inject into a component.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let hasWarnedAboutDeprecatedPureOption = false;
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Connects a React component to a Redux store.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * - Without arguments, just wraps the component, without changing the behavior / props
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * - If 2 params are passed (3rd param, mergeProps, is skipped), default behavior
							 | 
						||
| 
								 | 
							
								 * is to override ownProps (as stated in the docs), so what remains is everything that's
							 | 
						||
| 
								 | 
							
								 * not a state or dispatch prop
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * - When 3rd param is passed, we don't know if ownProps propagate and whether they
							 | 
						||
| 
								 | 
							
								 * should be valid component props, because it depends on mergeProps implementation.
							 | 
						||
| 
								 | 
							
								 * As such, it is the user's responsibility to extend ownProps interface from state or
							 | 
						||
| 
								 | 
							
								 * dispatch props or both when applicable
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param mapStateToProps A function that extracts values from state
							 | 
						||
| 
								 | 
							
								 * @param mapDispatchToProps Setup for dispatching actions
							 | 
						||
| 
								 | 
							
								 * @param mergeProps Optional callback to merge state and dispatch props together
							 | 
						||
| 
								 | 
							
								 * @param options Options for configuring the connection
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function connect(mapStateToProps, mapDispatchToProps, mergeProps, {
							 | 
						||
| 
								 | 
							
								  // The `pure` option has been removed, so TS doesn't like us destructuring this to check its existence.
							 | 
						||
| 
								 | 
							
								  // @ts-ignore
							 | 
						||
| 
								 | 
							
								  pure,
							 | 
						||
| 
								 | 
							
								  areStatesEqual = strictEqual,
							 | 
						||
| 
								 | 
							
								  areOwnPropsEqual = _shallowEqual.default,
							 | 
						||
| 
								 | 
							
								  areStatePropsEqual = _shallowEqual.default,
							 | 
						||
| 
								 | 
							
								  areMergedPropsEqual = _shallowEqual.default,
							 | 
						||
| 
								 | 
							
								  // use React's forwardRef to expose a ref of the wrapped component
							 | 
						||
| 
								 | 
							
								  forwardRef = false,
							 | 
						||
| 
								 | 
							
								  // the context consumer to use
							 | 
						||
| 
								 | 
							
								  context = _Context.ReactReduxContext
							 | 
						||
| 
								 | 
							
								} = {}) {
							 | 
						||
| 
								 | 
							
								  if (process.env.NODE_ENV !== 'production') {
							 | 
						||
| 
								 | 
							
								    if (pure !== undefined && !hasWarnedAboutDeprecatedPureOption) {
							 | 
						||
| 
								 | 
							
								      hasWarnedAboutDeprecatedPureOption = true;
							 | 
						||
| 
								 | 
							
								      (0, _warning.default)('The `pure` option has been removed. `connect` is now always a "pure/memoized" component');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const Context = context;
							 | 
						||
| 
								 | 
							
								  const initMapStateToProps = (0, _mapStateToProps.mapStateToPropsFactory)(mapStateToProps);
							 | 
						||
| 
								 | 
							
								  const initMapDispatchToProps = (0, _mapDispatchToProps.mapDispatchToPropsFactory)(mapDispatchToProps);
							 | 
						||
| 
								 | 
							
								  const initMergeProps = (0, _mergeProps.mergePropsFactory)(mergeProps);
							 | 
						||
| 
								 | 
							
								  const shouldHandleStateChanges = Boolean(mapStateToProps);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const wrapWithConnect = WrappedComponent => {
							 | 
						||
| 
								 | 
							
								    if (process.env.NODE_ENV !== 'production' && !(0, _reactIs.isValidElementType)(WrappedComponent)) {
							 | 
						||
| 
								 | 
							
								      throw new Error(`You must pass a component to the function returned by connect. Instead received ${stringifyComponent(WrappedComponent)}`);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
							 | 
						||
| 
								 | 
							
								    const displayName = `Connect(${wrappedComponentName})`;
							 | 
						||
| 
								 | 
							
								    const selectorFactoryOptions = {
							 | 
						||
| 
								 | 
							
								      shouldHandleStateChanges,
							 | 
						||
| 
								 | 
							
								      displayName,
							 | 
						||
| 
								 | 
							
								      wrappedComponentName,
							 | 
						||
| 
								 | 
							
								      WrappedComponent,
							 | 
						||
| 
								 | 
							
								      // @ts-ignore
							 | 
						||
| 
								 | 
							
								      initMapStateToProps,
							 | 
						||
| 
								 | 
							
								      // @ts-ignore
							 | 
						||
| 
								 | 
							
								      initMapDispatchToProps,
							 | 
						||
| 
								 | 
							
								      initMergeProps,
							 | 
						||
| 
								 | 
							
								      areStatesEqual,
							 | 
						||
| 
								 | 
							
								      areStatePropsEqual,
							 | 
						||
| 
								 | 
							
								      areOwnPropsEqual,
							 | 
						||
| 
								 | 
							
								      areMergedPropsEqual
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function ConnectFunction(props) {
							 | 
						||
| 
								 | 
							
								      const [propsContext, reactReduxForwardedRef, wrapperProps] = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        // Distinguish between actual "data" props that were passed to the wrapper component,
							 | 
						||
| 
								 | 
							
								        // and values needed to control behavior (forwarded refs, alternate context instances).
							 | 
						||
| 
								 | 
							
								        // To maintain the wrapperProps object reference, memoize this destructuring.
							 | 
						||
| 
								 | 
							
								        const {
							 | 
						||
| 
								 | 
							
								          reactReduxForwardedRef
							 | 
						||
| 
								 | 
							
								        } = props,
							 | 
						||
| 
								 | 
							
								              wrapperProps = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
							 | 
						||
| 
								 | 
							
								        return [props.context, reactReduxForwardedRef, wrapperProps];
							 | 
						||
| 
								 | 
							
								      }, [props]);
							 | 
						||
| 
								 | 
							
								      const ContextToUse = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        // Users may optionally pass in a custom context instance to use instead of our ReactReduxContext.
							 | 
						||
| 
								 | 
							
								        // Memoize the check that determines which context instance we should use.
							 | 
						||
| 
								 | 
							
								        return propsContext && propsContext.Consumer && // @ts-ignore
							 | 
						||
| 
								 | 
							
								        (0, _reactIs.isContextConsumer)( /*#__PURE__*/_react.default.createElement(propsContext.Consumer, null)) ? propsContext : Context;
							 | 
						||
| 
								 | 
							
								      }, [propsContext, Context]); // Retrieve the store and ancestor subscription via context, if available
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const contextValue = (0, _react.useContext)(ContextToUse); // The store _must_ exist as either a prop or in context.
							 | 
						||
| 
								 | 
							
								      // We'll check to see if it _looks_ like a Redux store first.
							 | 
						||
| 
								 | 
							
								      // This allows us to pass through a `store` prop that is just a plain value.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const didStoreComeFromProps = Boolean(props.store) && Boolean(props.store.getState) && Boolean(props.store.dispatch);
							 | 
						||
| 
								 | 
							
								      const didStoreComeFromContext = Boolean(contextValue) && Boolean(contextValue.store);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (process.env.NODE_ENV !== 'production' && !didStoreComeFromProps && !didStoreComeFromContext) {
							 | 
						||
| 
								 | 
							
								        throw new Error(`Could not find "store" in the context of ` + `"${displayName}". Either wrap the root component in a <Provider>, ` + `or pass a custom React context provider to <Provider> and the corresponding ` + `React context consumer to ${displayName} in connect options.`);
							 | 
						||
| 
								 | 
							
								      } // Based on the previous check, one of these must be true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const store = didStoreComeFromProps ? props.store : contextValue.store;
							 | 
						||
| 
								 | 
							
								      const getServerState = didStoreComeFromContext ? contextValue.getServerState : store.getState;
							 | 
						||
| 
								 | 
							
								      const childPropsSelector = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        // The child props selector needs the store reference as an input.
							 | 
						||
| 
								 | 
							
								        // Re-create this selector whenever the store changes.
							 | 
						||
| 
								 | 
							
								        return (0, _selectorFactory.default)(store.dispatch, selectorFactoryOptions);
							 | 
						||
| 
								 | 
							
								      }, [store]);
							 | 
						||
| 
								 | 
							
								      const [subscription, notifyNestedSubs] = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        if (!shouldHandleStateChanges) return NO_SUBSCRIPTION_ARRAY; // This Subscription's source should match where store came from: props vs. context. A component
							 | 
						||
| 
								 | 
							
								        // connected to the store via props shouldn't use subscription from context, or vice versa.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const subscription = (0, _Subscription.createSubscription)(store, didStoreComeFromProps ? undefined : contextValue.subscription); // `notifyNestedSubs` is duplicated to handle the case where the component is unmounted in
							 | 
						||
| 
								 | 
							
								        // the middle of the notification loop, where `subscription` will then be null. This can
							 | 
						||
| 
								 | 
							
								        // probably be avoided if Subscription's listeners logic is changed to not call listeners
							 | 
						||
| 
								 | 
							
								        // that have been unsubscribed in the  middle of the notification loop.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const notifyNestedSubs = subscription.notifyNestedSubs.bind(subscription);
							 | 
						||
| 
								 | 
							
								        return [subscription, notifyNestedSubs];
							 | 
						||
| 
								 | 
							
								      }, [store, didStoreComeFromProps, contextValue]); // Determine what {store, subscription} value should be put into nested context, if necessary,
							 | 
						||
| 
								 | 
							
								      // and memoize that value to avoid unnecessary context updates.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const overriddenContextValue = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        if (didStoreComeFromProps) {
							 | 
						||
| 
								 | 
							
								          // This component is directly subscribed to a store from props.
							 | 
						||
| 
								 | 
							
								          // We don't want descendants reading from this store - pass down whatever
							 | 
						||
| 
								 | 
							
								          // the existing context value is from the nearest connected ancestor.
							 | 
						||
| 
								 | 
							
								          return contextValue;
							 | 
						||
| 
								 | 
							
								        } // Otherwise, put this component's subscription instance into context, so that
							 | 
						||
| 
								 | 
							
								        // connected descendants won't update until after this component is done
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return (0, _extends2.default)({}, contextValue, {
							 | 
						||
| 
								 | 
							
								          subscription
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }, [didStoreComeFromProps, contextValue, subscription]); // Set up refs to coordinate values between the subscription effect and the render logic
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const lastChildProps = (0, _react.useRef)();
							 | 
						||
| 
								 | 
							
								      const lastWrapperProps = (0, _react.useRef)(wrapperProps);
							 | 
						||
| 
								 | 
							
								      const childPropsFromStoreUpdate = (0, _react.useRef)();
							 | 
						||
| 
								 | 
							
								      const renderIsScheduled = (0, _react.useRef)(false);
							 | 
						||
| 
								 | 
							
								      const isProcessingDispatch = (0, _react.useRef)(false);
							 | 
						||
| 
								 | 
							
								      const isMounted = (0, _react.useRef)(false);
							 | 
						||
| 
								 | 
							
								      const latestSubscriptionCallbackError = (0, _react.useRef)();
							 | 
						||
| 
								 | 
							
								      (0, _useIsomorphicLayoutEffect.useIsomorphicLayoutEffect)(() => {
							 | 
						||
| 
								 | 
							
								        isMounted.current = true;
							 | 
						||
| 
								 | 
							
								        return () => {
							 | 
						||
| 
								 | 
							
								          isMounted.current = false;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }, []);
							 | 
						||
| 
								 | 
							
								      const actualChildPropsSelector = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        const selector = () => {
							 | 
						||
| 
								 | 
							
								          // Tricky logic here:
							 | 
						||
| 
								 | 
							
								          // - This render may have been triggered by a Redux store update that produced new child props
							 | 
						||
| 
								 | 
							
								          // - However, we may have gotten new wrapper props after that
							 | 
						||
| 
								 | 
							
								          // If we have new child props, and the same wrapper props, we know we should use the new child props as-is.
							 | 
						||
| 
								 | 
							
								          // But, if we have new wrapper props, those might change the child props, so we have to recalculate things.
							 | 
						||
| 
								 | 
							
								          // So, we'll use the child props from store update only if the wrapper props are the same as last time.
							 | 
						||
| 
								 | 
							
								          if (childPropsFromStoreUpdate.current && wrapperProps === lastWrapperProps.current) {
							 | 
						||
| 
								 | 
							
								            return childPropsFromStoreUpdate.current;
							 | 
						||
| 
								 | 
							
								          } // TODO We're reading the store directly in render() here. Bad idea?
							 | 
						||
| 
								 | 
							
								          // This will likely cause Bad Things (TM) to happen in Concurrent Mode.
							 | 
						||
| 
								 | 
							
								          // Note that we do this because on renders _not_ caused by store updates, we need the latest store state
							 | 
						||
| 
								 | 
							
								          // to determine what the child props should be.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          return childPropsSelector(store.getState(), wrapperProps);
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return selector;
							 | 
						||
| 
								 | 
							
								      }, [store, wrapperProps]); // We need this to execute synchronously every time we re-render. However, React warns
							 | 
						||
| 
								 | 
							
								      // about useLayoutEffect in SSR, so we try to detect environment and fall back to
							 | 
						||
| 
								 | 
							
								      // just useEffect instead to avoid the warning, since neither will run anyway.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const subscribeForReact = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        const subscribe = reactListener => {
							 | 
						||
| 
								 | 
							
								          if (!subscription) {
							 | 
						||
| 
								 | 
							
								            return () => {};
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          return subscribeUpdates(shouldHandleStateChanges, store, subscription, // @ts-ignore
							 | 
						||
| 
								 | 
							
								          childPropsSelector, lastWrapperProps, lastChildProps, renderIsScheduled, isMounted, childPropsFromStoreUpdate, notifyNestedSubs, reactListener);
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return subscribe;
							 | 
						||
| 
								 | 
							
								      }, [subscription]);
							 | 
						||
| 
								 | 
							
								      useIsomorphicLayoutEffectWithArgs(captureWrapperProps, [lastWrapperProps, lastChildProps, renderIsScheduled, wrapperProps, childPropsFromStoreUpdate, notifyNestedSubs]);
							 | 
						||
| 
								 | 
							
								      let actualChildProps;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        actualChildProps = useSyncExternalStore( // TODO We're passing through a big wrapper that does a bunch of extra side effects besides subscribing
							 | 
						||
| 
								 | 
							
								        subscribeForReact, // TODO This is incredibly hacky. We've already processed the store update and calculated new child props,
							 | 
						||
| 
								 | 
							
								        // TODO and we're just passing that through so it triggers a re-render for us rather than relying on `uSES`.
							 | 
						||
| 
								 | 
							
								        actualChildPropsSelector, getServerState ? () => childPropsSelector(getServerState(), wrapperProps) : actualChildPropsSelector);
							 | 
						||
| 
								 | 
							
								      } catch (err) {
							 | 
						||
| 
								 | 
							
								        if (latestSubscriptionCallbackError.current) {
							 | 
						||
| 
								 | 
							
								          ;
							 | 
						||
| 
								 | 
							
								          err.message += `\nThe error may be correlated with this previous error:\n${latestSubscriptionCallbackError.current.stack}\n\n`;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        throw err;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      (0, _useIsomorphicLayoutEffect.useIsomorphicLayoutEffect)(() => {
							 | 
						||
| 
								 | 
							
								        latestSubscriptionCallbackError.current = undefined;
							 | 
						||
| 
								 | 
							
								        childPropsFromStoreUpdate.current = undefined;
							 | 
						||
| 
								 | 
							
								        lastChildProps.current = actualChildProps;
							 | 
						||
| 
								 | 
							
								      }); // Now that all that's done, we can finally try to actually render the child component.
							 | 
						||
| 
								 | 
							
								      // We memoize the elements for the rendered child component as an optimization.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const renderedWrappedComponent = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        return (
							 | 
						||
| 
								 | 
							
								          /*#__PURE__*/
							 | 
						||
| 
								 | 
							
								          // @ts-ignore
							 | 
						||
| 
								 | 
							
								          _react.default.createElement(WrappedComponent, (0, _extends2.default)({}, actualChildProps, {
							 | 
						||
| 
								 | 
							
								            ref: reactReduxForwardedRef
							 | 
						||
| 
								 | 
							
								          }))
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								      }, [reactReduxForwardedRef, WrappedComponent, actualChildProps]); // If React sees the exact same element reference as last time, it bails out of re-rendering
							 | 
						||
| 
								 | 
							
								      // that child, same as if it was wrapped in React.memo() or returned false from shouldComponentUpdate.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const renderedChild = (0, _react.useMemo)(() => {
							 | 
						||
| 
								 | 
							
								        if (shouldHandleStateChanges) {
							 | 
						||
| 
								 | 
							
								          // If this component is subscribed to store updates, we need to pass its own
							 | 
						||
| 
								 | 
							
								          // subscription instance down to our descendants. That means rendering the same
							 | 
						||
| 
								 | 
							
								          // Context instance, and putting a different value into the context.
							 | 
						||
| 
								 | 
							
								          return /*#__PURE__*/_react.default.createElement(ContextToUse.Provider, {
							 | 
						||
| 
								 | 
							
								            value: overriddenContextValue
							 | 
						||
| 
								 | 
							
								          }, renderedWrappedComponent);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return renderedWrappedComponent;
							 | 
						||
| 
								 | 
							
								      }, [ContextToUse, renderedWrappedComponent, overriddenContextValue]);
							 | 
						||
| 
								 | 
							
								      return renderedChild;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const _Connect = _react.default.memo(ConnectFunction);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Add a hacky cast to get the right output type
							 | 
						||
| 
								 | 
							
								    const Connect = _Connect;
							 | 
						||
| 
								 | 
							
								    Connect.WrappedComponent = WrappedComponent;
							 | 
						||
| 
								 | 
							
								    Connect.displayName = ConnectFunction.displayName = displayName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (forwardRef) {
							 | 
						||
| 
								 | 
							
								      const _forwarded = _react.default.forwardRef(function forwardConnectRef(props, ref) {
							 | 
						||
| 
								 | 
							
								        // @ts-ignore
							 | 
						||
| 
								 | 
							
								        return /*#__PURE__*/_react.default.createElement(Connect, (0, _extends2.default)({}, props, {
							 | 
						||
| 
								 | 
							
								          reactReduxForwardedRef: ref
							 | 
						||
| 
								 | 
							
								        }));
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const forwarded = _forwarded;
							 | 
						||
| 
								 | 
							
								      forwarded.displayName = displayName;
							 | 
						||
| 
								 | 
							
								      forwarded.WrappedComponent = WrappedComponent;
							 | 
						||
| 
								 | 
							
								      return (0, _hoistNonReactStatics.default)(forwarded, WrappedComponent);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (0, _hoistNonReactStatics.default)(Connect, WrappedComponent);
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return wrapWithConnect;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _default = connect;
							 | 
						||
| 
								 | 
							
								exports.default = _default;
							 |