source: node_modules/react-redux/src/connect/selectorFactory.ts

Last change on this file was a762898, checked in by istevanoska <ilinastevanoska@…>, 5 months ago

Added visualizations

  • Property mode set to 100644
File size: 7.5 KB
Line 
1import type { Dispatch, Action } from 'redux'
2import type { ComponentType } from 'react'
3import verifySubselectors from './verifySubselectors'
4import type { EqualityFn, ExtendedEqualityFn } from '../types'
5
6export type SelectorFactory<S, TProps, TOwnProps, TFactoryOptions> = (
7 dispatch: Dispatch<Action<string>>,
8 factoryOptions: TFactoryOptions,
9) => Selector<S, TProps, TOwnProps>
10
11export type Selector<S, TProps, TOwnProps = null> = TOwnProps extends
12 | null
13 | undefined
14 ? (state: S) => TProps
15 : (state: S, ownProps: TOwnProps) => TProps
16
17export type MapStateToProps<TStateProps, TOwnProps, State> = (
18 state: State,
19 ownProps: TOwnProps,
20) => TStateProps
21
22export type MapStateToPropsFactory<TStateProps, TOwnProps, State> = (
23 initialState: State,
24 ownProps: TOwnProps,
25) => MapStateToProps<TStateProps, TOwnProps, State>
26
27export type MapStateToPropsParam<TStateProps, TOwnProps, State> =
28 | MapStateToPropsFactory<TStateProps, TOwnProps, State>
29 | MapStateToProps<TStateProps, TOwnProps, State>
30 | null
31 | undefined
32
33export type MapDispatchToPropsFunction<TDispatchProps, TOwnProps> = (
34 dispatch: Dispatch<Action<string>>,
35 ownProps: TOwnProps,
36) => TDispatchProps
37
38export type MapDispatchToProps<TDispatchProps, TOwnProps> =
39 | MapDispatchToPropsFunction<TDispatchProps, TOwnProps>
40 | TDispatchProps
41
42export type MapDispatchToPropsFactory<TDispatchProps, TOwnProps> = (
43 dispatch: Dispatch<Action<string>>,
44 ownProps: TOwnProps,
45) => MapDispatchToPropsFunction<TDispatchProps, TOwnProps>
46
47export type MapDispatchToPropsParam<TDispatchProps, TOwnProps> =
48 | MapDispatchToPropsFactory<TDispatchProps, TOwnProps>
49 | MapDispatchToProps<TDispatchProps, TOwnProps>
50
51export type MapDispatchToPropsNonObject<TDispatchProps, TOwnProps> =
52 | MapDispatchToPropsFactory<TDispatchProps, TOwnProps>
53 | MapDispatchToPropsFunction<TDispatchProps, TOwnProps>
54
55export type MergeProps<TStateProps, TDispatchProps, TOwnProps, TMergedProps> = (
56 stateProps: TStateProps,
57 dispatchProps: TDispatchProps,
58 ownProps: TOwnProps,
59) => TMergedProps
60
61interface PureSelectorFactoryComparisonOptions<TStateProps, TOwnProps, State> {
62 readonly areStatesEqual: ExtendedEqualityFn<State, TOwnProps>
63 readonly areStatePropsEqual: EqualityFn<TStateProps>
64 readonly areOwnPropsEqual: EqualityFn<TOwnProps>
65}
66
67function pureFinalPropsSelectorFactory<
68 TStateProps,
69 TOwnProps,
70 TDispatchProps,
71 TMergedProps,
72 State,
73>(
74 mapStateToProps: WrappedMapStateToProps<TStateProps, TOwnProps, State>,
75 mapDispatchToProps: WrappedMapDispatchToProps<TDispatchProps, TOwnProps>,
76 mergeProps: MergeProps<TStateProps, TDispatchProps, TOwnProps, TMergedProps>,
77 dispatch: Dispatch<Action<string>>,
78 {
79 areStatesEqual,
80 areOwnPropsEqual,
81 areStatePropsEqual,
82 }: PureSelectorFactoryComparisonOptions<TStateProps, TOwnProps, State>,
83) {
84 let hasRunAtLeastOnce = false
85 let state: State
86 let ownProps: TOwnProps
87 let stateProps: TStateProps
88 let dispatchProps: TDispatchProps
89 let mergedProps: TMergedProps
90
91 function handleFirstCall(firstState: State, firstOwnProps: TOwnProps) {
92 state = firstState
93 ownProps = firstOwnProps
94 stateProps = mapStateToProps(state, ownProps)
95 dispatchProps = mapDispatchToProps(dispatch, ownProps)
96 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
97 hasRunAtLeastOnce = true
98 return mergedProps
99 }
100
101 function handleNewPropsAndNewState() {
102 stateProps = mapStateToProps(state, ownProps)
103
104 if (mapDispatchToProps.dependsOnOwnProps)
105 dispatchProps = mapDispatchToProps(dispatch, ownProps)
106
107 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
108 return mergedProps
109 }
110
111 function handleNewProps() {
112 if (mapStateToProps.dependsOnOwnProps)
113 stateProps = mapStateToProps(state, ownProps)
114
115 if (mapDispatchToProps.dependsOnOwnProps)
116 dispatchProps = mapDispatchToProps(dispatch, ownProps)
117
118 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
119 return mergedProps
120 }
121
122 function handleNewState() {
123 const nextStateProps = mapStateToProps(state, ownProps)
124 const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps)
125 stateProps = nextStateProps
126
127 if (statePropsChanged)
128 mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
129
130 return mergedProps
131 }
132
133 function handleSubsequentCalls(nextState: State, nextOwnProps: TOwnProps) {
134 const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps)
135 const stateChanged = !areStatesEqual(
136 nextState,
137 state,
138 nextOwnProps,
139 ownProps,
140 )
141 state = nextState
142 ownProps = nextOwnProps
143
144 if (propsChanged && stateChanged) return handleNewPropsAndNewState()
145 if (propsChanged) return handleNewProps()
146 if (stateChanged) return handleNewState()
147 return mergedProps
148 }
149
150 return function pureFinalPropsSelector(
151 nextState: State,
152 nextOwnProps: TOwnProps,
153 ) {
154 return hasRunAtLeastOnce
155 ? handleSubsequentCalls(nextState, nextOwnProps)
156 : handleFirstCall(nextState, nextOwnProps)
157 }
158}
159
160interface WrappedMapStateToProps<TStateProps, TOwnProps, State> {
161 (state: State, ownProps: TOwnProps): TStateProps
162 readonly dependsOnOwnProps: boolean
163}
164
165interface WrappedMapDispatchToProps<TDispatchProps, TOwnProps> {
166 (dispatch: Dispatch<Action<string>>, ownProps: TOwnProps): TDispatchProps
167 readonly dependsOnOwnProps: boolean
168}
169
170export interface InitOptions<TStateProps, TOwnProps, TMergedProps, State>
171 extends PureSelectorFactoryComparisonOptions<TStateProps, TOwnProps, State> {
172 readonly shouldHandleStateChanges: boolean
173 readonly displayName: string
174 readonly wrappedComponentName: string
175 readonly WrappedComponent: ComponentType<TOwnProps>
176 readonly areMergedPropsEqual: EqualityFn<TMergedProps>
177}
178
179export interface SelectorFactoryOptions<
180 TStateProps,
181 TOwnProps,
182 TDispatchProps,
183 TMergedProps,
184 State,
185> extends InitOptions<TStateProps, TOwnProps, TMergedProps, State> {
186 readonly initMapStateToProps: (
187 dispatch: Dispatch<Action<string>>,
188 options: InitOptions<TStateProps, TOwnProps, TMergedProps, State>,
189 ) => WrappedMapStateToProps<TStateProps, TOwnProps, State>
190 readonly initMapDispatchToProps: (
191 dispatch: Dispatch<Action<string>>,
192 options: InitOptions<TStateProps, TOwnProps, TMergedProps, State>,
193 ) => WrappedMapDispatchToProps<TDispatchProps, TOwnProps>
194 readonly initMergeProps: (
195 dispatch: Dispatch<Action<string>>,
196 options: InitOptions<TStateProps, TOwnProps, TMergedProps, State>,
197 ) => MergeProps<TStateProps, TDispatchProps, TOwnProps, TMergedProps>
198}
199
200// TODO: Add more comments
201
202// The selector returned by selectorFactory will memoize its results,
203// allowing connect's shouldComponentUpdate to return false if final
204// props have not changed.
205
206export default function finalPropsSelectorFactory<
207 TStateProps,
208 TOwnProps,
209 TDispatchProps,
210 TMergedProps,
211 State,
212>(
213 dispatch: Dispatch<Action<string>>,
214 {
215 initMapStateToProps,
216 initMapDispatchToProps,
217 initMergeProps,
218 ...options
219 }: SelectorFactoryOptions<
220 TStateProps,
221 TOwnProps,
222 TDispatchProps,
223 TMergedProps,
224 State
225 >,
226) {
227 const mapStateToProps = initMapStateToProps(dispatch, options)
228 const mapDispatchToProps = initMapDispatchToProps(dispatch, options)
229 const mergeProps = initMergeProps(dispatch, options)
230
231 if (process.env.NODE_ENV !== 'production') {
232 verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps)
233 }
234
235 return pureFinalPropsSelectorFactory<
236 TStateProps,
237 TOwnProps,
238 TDispatchProps,
239 TMergedProps,
240 State
241 >(mapStateToProps, mapDispatchToProps, mergeProps, dispatch, options)
242}
Note: See TracBrowser for help on using the repository browser.