| [a762898] | 1 | import type { ActionCreatorsMapObject, Dispatch, ActionCreator } from 'redux'
|
|---|
| 2 |
|
|---|
| 3 | import type { FixTypeLater } from '../types'
|
|---|
| 4 | import verifyPlainObject from '../utils/verifyPlainObject'
|
|---|
| 5 |
|
|---|
| 6 | type AnyState = { [key: string]: any }
|
|---|
| 7 | type StateOrDispatch<S extends AnyState = AnyState> = S | Dispatch
|
|---|
| 8 |
|
|---|
| 9 | type AnyProps = { [key: string]: any }
|
|---|
| 10 |
|
|---|
| 11 | export type MapToProps<P extends AnyProps = AnyProps> = {
|
|---|
| 12 | // eslint-disable-next-line no-unused-vars
|
|---|
| 13 | (stateOrDispatch: StateOrDispatch, ownProps?: P): FixTypeLater
|
|---|
| 14 | dependsOnOwnProps?: boolean
|
|---|
| 15 | }
|
|---|
| 16 |
|
|---|
| 17 | export function wrapMapToPropsConstant(
|
|---|
| 18 | // * Note:
|
|---|
| 19 | // It seems that the dispatch argument
|
|---|
| 20 | // could be a dispatch function in some cases (ex: whenMapDispatchToPropsIsMissing)
|
|---|
| 21 | // and a state object in some others (ex: whenMapStateToPropsIsMissing)
|
|---|
| 22 | // eslint-disable-next-line no-unused-vars
|
|---|
| 23 | getConstant: (dispatch: Dispatch) =>
|
|---|
| 24 | | {
|
|---|
| 25 | dispatch?: Dispatch
|
|---|
| 26 | dependsOnOwnProps?: boolean
|
|---|
| 27 | }
|
|---|
| 28 | | ActionCreatorsMapObject
|
|---|
| 29 | | ActionCreator<any>,
|
|---|
| 30 | ) {
|
|---|
| 31 | return function initConstantSelector(dispatch: Dispatch) {
|
|---|
| 32 | const constant = getConstant(dispatch)
|
|---|
| 33 |
|
|---|
| 34 | function constantSelector() {
|
|---|
| 35 | return constant
|
|---|
| 36 | }
|
|---|
| 37 | constantSelector.dependsOnOwnProps = false
|
|---|
| 38 | return constantSelector
|
|---|
| 39 | }
|
|---|
| 40 | }
|
|---|
| 41 |
|
|---|
| 42 | // dependsOnOwnProps is used by createMapToPropsProxy to determine whether to pass props as args
|
|---|
| 43 | // to the mapToProps function being wrapped. It is also used by makePurePropsSelector to determine
|
|---|
| 44 | // whether mapToProps needs to be invoked when props have changed.
|
|---|
| 45 | //
|
|---|
| 46 | // A length of one signals that mapToProps does not depend on props from the parent component.
|
|---|
| 47 | // A length of zero is assumed to mean mapToProps is getting args via arguments or ...args and
|
|---|
| 48 | // therefore not reporting its length accurately..
|
|---|
| 49 | // TODO Can this get pulled out so that we can subscribe directly to the store if we don't need ownProps?
|
|---|
| 50 | function getDependsOnOwnProps(mapToProps: MapToProps) {
|
|---|
| 51 | return mapToProps.dependsOnOwnProps
|
|---|
| 52 | ? Boolean(mapToProps.dependsOnOwnProps)
|
|---|
| 53 | : mapToProps.length !== 1
|
|---|
| 54 | }
|
|---|
| 55 |
|
|---|
| 56 | // Used by whenMapStateToPropsIsFunction and whenMapDispatchToPropsIsFunction,
|
|---|
| 57 | // this function wraps mapToProps in a proxy function which does several things:
|
|---|
| 58 | //
|
|---|
| 59 | // * Detects whether the mapToProps function being called depends on props, which
|
|---|
| 60 | // is used by selectorFactory to decide if it should reinvoke on props changes.
|
|---|
| 61 | //
|
|---|
| 62 | // * On first call, handles mapToProps if returns another function, and treats that
|
|---|
| 63 | // new function as the true mapToProps for subsequent calls.
|
|---|
| 64 | //
|
|---|
| 65 | // * On first call, verifies the first result is a plain object, in order to warn
|
|---|
| 66 | // the developer that their mapToProps function is not returning a valid result.
|
|---|
| 67 | //
|
|---|
| 68 | export function wrapMapToPropsFunc<P extends AnyProps = AnyProps>(
|
|---|
| 69 | mapToProps: MapToProps,
|
|---|
| 70 | methodName: string,
|
|---|
| 71 | ) {
|
|---|
| 72 | return function initProxySelector(
|
|---|
| 73 | dispatch: Dispatch,
|
|---|
| 74 | { displayName }: { displayName: string },
|
|---|
| 75 | ) {
|
|---|
| 76 | const proxy = function mapToPropsProxy(
|
|---|
| 77 | stateOrDispatch: StateOrDispatch,
|
|---|
| 78 | ownProps?: P,
|
|---|
| 79 | ): MapToProps {
|
|---|
| 80 | return proxy.dependsOnOwnProps
|
|---|
| 81 | ? proxy.mapToProps(stateOrDispatch, ownProps)
|
|---|
| 82 | : proxy.mapToProps(stateOrDispatch, undefined)
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | // allow detectFactoryAndVerify to get ownProps
|
|---|
| 86 | proxy.dependsOnOwnProps = true
|
|---|
| 87 |
|
|---|
| 88 | proxy.mapToProps = function detectFactoryAndVerify(
|
|---|
| 89 | stateOrDispatch: StateOrDispatch,
|
|---|
| 90 | ownProps?: P,
|
|---|
| 91 | ): MapToProps {
|
|---|
| 92 | proxy.mapToProps = mapToProps
|
|---|
| 93 | proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps)
|
|---|
| 94 | let props = proxy(stateOrDispatch, ownProps)
|
|---|
| 95 |
|
|---|
| 96 | if (typeof props === 'function') {
|
|---|
| 97 | proxy.mapToProps = props
|
|---|
| 98 | proxy.dependsOnOwnProps = getDependsOnOwnProps(props)
|
|---|
| 99 | props = proxy(stateOrDispatch, ownProps)
|
|---|
| 100 | }
|
|---|
| 101 |
|
|---|
| 102 | if (process.env.NODE_ENV !== 'production')
|
|---|
| 103 | verifyPlainObject(props, displayName, methodName)
|
|---|
| 104 |
|
|---|
| 105 | return props
|
|---|
| 106 | }
|
|---|
| 107 |
|
|---|
| 108 | return proxy
|
|---|
| 109 | }
|
|---|
| 110 | }
|
|---|