@@ -168,18 +168,20 @@ export default function connectAdvanced(
168168 // Retrieve the store and ancestor subscription via context, if available
169169 const contextValue = useContext ( ContextToUse )
170170
171-
172171 // The store _must_ exist as either a prop or in context
172+ const didStoreComeFromProps = Boolean ( props . store )
173+ const didStoreComeFromContext =
174+ Boolean ( contextValue ) && Boolean ( contextValue . store )
175+
173176 invariant (
174- props . store || contextValue ,
177+ didStoreComeFromProps || didStoreComeFromContext ,
175178 `Could not find "store" in the context of ` +
176179 `"${ displayName } ". Either wrap the root component in a <Provider>, ` +
177180 `or pass a custom React context provider to <Provider> and the corresponding ` +
178181 `React context consumer to ${ displayName } in connect options.`
179182 )
180183
181184 const store = props . store || contextValue . store
182- const propsMode = Boolean ( props . store )
183185
184186 const childPropsSelector = useMemo ( ( ) => {
185187 // The child props selector needs the store reference as an input.
@@ -190,9 +192,12 @@ export default function connectAdvanced(
190192 const [ subscription , notifyNestedSubs ] = useMemo ( ( ) => {
191193 if ( ! shouldHandleStateChanges ) return NO_SUBSCRIPTION_ARRAY
192194
193- // parentSub 's source should match where store came from: props vs. context. A component
195+ // This Subscription 's source should match where store came from: props vs. context. A component
194196 // connected to the store via props shouldn't use subscription from context, or vice versa.
195- const subscription = new Subscription ( store , contextValue . subscription )
197+ const subscription = new Subscription (
198+ store ,
199+ didStoreComeFromProps ? null : contextValue . subscription
200+ )
196201
197202 // `notifyNestedSubs` is duplicated to handle the case where the component is unmounted in
198203 // the middle of the notification loop, where `subscription` will then be null. This can
@@ -203,26 +208,32 @@ export default function connectAdvanced(
203208 )
204209
205210 return [ subscription , notifyNestedSubs ]
206- } , [ store , contextValue . subscription ] )
211+ } , [ store , didStoreComeFromProps , contextValue ] )
207212
208- // Determine what {store, subscription} value should be put into nested context, if necessary
213+ // Determine what {store, subscription} value should be put into nested context, if necessary,
214+ // and memoize that value to avoid unnecessary context updates.
209215 const overriddenContextValue = useMemo ( ( ) => {
216+ if ( didStoreComeFromProps ) {
217+ // This component is directly subscribed to a store from props.
218+ // We don't want descendants reading from this store - pass down whatever
219+ // the existing context value is from the nearest connected ancestor.
220+ return contextValue
221+ }
210222
211223 // Otherwise, put this component's subscription instance into context, so that
212224 // connected descendants won't update until after this component is done
213225 return {
214226 ...contextValue ,
215227 subscription
216228 }
217- } , [ contextValue , subscription ] )
229+ } , [ didStoreComeFromProps , contextValue , subscription ] )
218230
219231 // We need to force this wrapper component to re-render whenever a Redux store update
220232 // causes a change to the calculated child component props (or we caught an error in mapState)
221- const [ [ previousStateUpdateResult ] , forceComponentUpdateDispatch ] = useReducer (
222- storeStateUpdatesReducer ,
223- EMPTY_ARRAY ,
224- initStateUpdates
225- )
233+ const [
234+ [ previousStateUpdateResult ] ,
235+ forceComponentUpdateDispatch
236+ ] = useReducer ( storeStateUpdatesReducer , EMPTY_ARRAY , initStateUpdates )
226237
227238 // Propagate any mapState/mapDispatch errors upwards
228239 if ( previousStateUpdateResult && previousStateUpdateResult . error ) {
0 commit comments