From 458415b961534eba6383d6fd9546353bae195ad1 Mon Sep 17 00:00:00 2001 From: "REDMOND\\jspurlin" Date: Thu, 25 Aug 2022 12:43:20 -0700 Subject: [PATCH 1/7] Connect: pass ownProps to areStatesEqual --- src/components/connect.tsx | 7 ++++++- src/connect/selectorFactory.ts | 11 ++++++++--- src/types.ts | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/components/connect.tsx b/src/components/connect.tsx index 19116df41..9e5c00ba7 100644 --- a/src/components/connect.tsx +++ b/src/components/connect.tsx @@ -231,7 +231,12 @@ export interface ConnectOptions< > { forwardRef?: boolean context?: typeof ReactReduxContext - areStatesEqual?: (nextState: State, prevState: State) => boolean + areStatesEqual?: ( + nextState: State, + prevState: State, + nextOwnProps: TOwnProps, + prevOwnProps: TOwnProps + ) => boolean areOwnPropsEqual?: ( nextOwnProps: TOwnProps, diff --git a/src/connect/selectorFactory.ts b/src/connect/selectorFactory.ts index f0420a3f1..11620637a 100644 --- a/src/connect/selectorFactory.ts +++ b/src/connect/selectorFactory.ts @@ -1,7 +1,7 @@ import type { Dispatch, Action } from 'redux' import type { ComponentType } from 'react' import verifySubselectors from './verifySubselectors' -import type { EqualityFn } from '../types' +import type { EqualityFn, ExtendedEqualityFn } from '../types' export type SelectorFactory = ( dispatch: Dispatch>, @@ -59,7 +59,7 @@ export type MergeProps = ( ) => TMergedProps interface PureSelectorFactoryComparisonOptions { - readonly areStatesEqual: EqualityFn + readonly areStatesEqual: ExtendedEqualityFn readonly areStatePropsEqual: EqualityFn readonly areOwnPropsEqual: EqualityFn } @@ -132,7 +132,12 @@ export function pureFinalPropsSelectorFactory< function handleSubsequentCalls(nextState: State, nextOwnProps: TOwnProps) { const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps) - const stateChanged = !areStatesEqual(nextState, state) + const stateChanged = !areStatesEqual( + nextState, + state, + nextOwnProps, + ownProps + ) state = nextState ownProps = nextOwnProps diff --git a/src/types.ts b/src/types.ts index 599a568a3..fc4118642 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,6 +10,8 @@ export type FixTypeLater = any export type EqualityFn = (a: T, b: T) => boolean +export type ExtendedEqualityFn = (a: T, b: T, c: P, d: P) => boolean + export type AnyIfEmpty = keyof T extends never ? any : T export type DistributiveOmit = T extends unknown From fa597b57f4698021bf01680bce885aaa38a95d8a Mon Sep 17 00:00:00 2001 From: "REDMOND\\jspurlin" Date: Thu, 25 Aug 2022 12:53:15 -0700 Subject: [PATCH 2/7] update connect docs --- docs/api/connect.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/connect.md b/docs/api/connect.md index 2b87d6b6c..112b728ce 100644 --- a/docs/api/connect.md +++ b/docs/api/connect.md @@ -233,7 +233,7 @@ connect(mapStateToProps, mapDispatchToProps, null, { context: MyContext })( ) ``` -#### `areStatesEqual: (next: Object, prev: Object) => boolean` +#### `areStatesEqual: (next: Object, prev: Object, nextOwnProps: Object, prevOwnProps: Object) => boolean` - default value: `strictEqual: (next, prev) => prev === next` @@ -244,7 +244,7 @@ const areStatesEqual = (next, prev) => prev.entities.todos === next.entities.todos ``` -You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. +You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. Additionally, `areStatesEqual` provides `nextOwnProps` and `prevOwnProps` to allow for more effective scoping of your state which your connected component is interested in, if needed. This would likely impact the other equality checks as well, depending on your `mapStateToProps` function. From 034e0775a1824ba5ae295b68c73d05105c6ce6c0 Mon Sep 17 00:00:00 2001 From: jspurlin Date: Mon, 29 Aug 2022 09:36:29 -0700 Subject: [PATCH 3/7] Update connect.md remove extra space in connect.md --- docs/api/connect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/connect.md b/docs/api/connect.md index 112b728ce..9e42fb421 100644 --- a/docs/api/connect.md +++ b/docs/api/connect.md @@ -244,7 +244,7 @@ const areStatesEqual = (next, prev) => prev.entities.todos === next.entities.todos ``` -You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. Additionally, `areStatesEqual` provides `nextOwnProps` and `prevOwnProps` to allow for more effective scoping of your state which your connected component is interested in, if needed. +You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. Additionally, `areStatesEqual` provides `nextOwnProps` and `prevOwnProps` to allow for more effective scoping of your state which your connected component is interested in, if needed. This would likely impact the other equality checks as well, depending on your `mapStateToProps` function. From a397801aa6de35945d5497ca73d11be8aeae49f2 Mon Sep 17 00:00:00 2001 From: "REDMOND\\jspurlin" Date: Thu, 25 Aug 2022 12:43:20 -0700 Subject: [PATCH 4/7] Connect: pass ownProps to areStatesEqual --- src/components/connect.tsx | 7 ++++++- src/connect/selectorFactory.ts | 11 ++++++++--- src/types.ts | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/components/connect.tsx b/src/components/connect.tsx index a598eacf7..be11ee4d1 100644 --- a/src/components/connect.tsx +++ b/src/components/connect.tsx @@ -231,7 +231,12 @@ export interface ConnectOptions< > { forwardRef?: boolean context?: typeof ReactReduxContext - areStatesEqual?: (nextState: State, prevState: State) => boolean + areStatesEqual?: ( + nextState: State, + prevState: State, + nextOwnProps: TOwnProps, + prevOwnProps: TOwnProps + ) => boolean areOwnPropsEqual?: ( nextOwnProps: TOwnProps, diff --git a/src/connect/selectorFactory.ts b/src/connect/selectorFactory.ts index f0420a3f1..11620637a 100644 --- a/src/connect/selectorFactory.ts +++ b/src/connect/selectorFactory.ts @@ -1,7 +1,7 @@ import type { Dispatch, Action } from 'redux' import type { ComponentType } from 'react' import verifySubselectors from './verifySubselectors' -import type { EqualityFn } from '../types' +import type { EqualityFn, ExtendedEqualityFn } from '../types' export type SelectorFactory = ( dispatch: Dispatch>, @@ -59,7 +59,7 @@ export type MergeProps = ( ) => TMergedProps interface PureSelectorFactoryComparisonOptions { - readonly areStatesEqual: EqualityFn + readonly areStatesEqual: ExtendedEqualityFn readonly areStatePropsEqual: EqualityFn readonly areOwnPropsEqual: EqualityFn } @@ -132,7 +132,12 @@ export function pureFinalPropsSelectorFactory< function handleSubsequentCalls(nextState: State, nextOwnProps: TOwnProps) { const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps) - const stateChanged = !areStatesEqual(nextState, state) + const stateChanged = !areStatesEqual( + nextState, + state, + nextOwnProps, + ownProps + ) state = nextState ownProps = nextOwnProps diff --git a/src/types.ts b/src/types.ts index 599a568a3..fc4118642 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,6 +10,8 @@ export type FixTypeLater = any export type EqualityFn = (a: T, b: T) => boolean +export type ExtendedEqualityFn = (a: T, b: T, c: P, d: P) => boolean + export type AnyIfEmpty = keyof T extends never ? any : T export type DistributiveOmit = T extends unknown From 0846e26c200705689e51aad6a743504ed74c0219 Mon Sep 17 00:00:00 2001 From: "REDMOND\\jspurlin" Date: Thu, 25 Aug 2022 12:53:15 -0700 Subject: [PATCH 5/7] update connect docs --- docs/api/connect.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/connect.md b/docs/api/connect.md index 2b87d6b6c..112b728ce 100644 --- a/docs/api/connect.md +++ b/docs/api/connect.md @@ -233,7 +233,7 @@ connect(mapStateToProps, mapDispatchToProps, null, { context: MyContext })( ) ``` -#### `areStatesEqual: (next: Object, prev: Object) => boolean` +#### `areStatesEqual: (next: Object, prev: Object, nextOwnProps: Object, prevOwnProps: Object) => boolean` - default value: `strictEqual: (next, prev) => prev === next` @@ -244,7 +244,7 @@ const areStatesEqual = (next, prev) => prev.entities.todos === next.entities.todos ``` -You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. +You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. Additionally, `areStatesEqual` provides `nextOwnProps` and `prevOwnProps` to allow for more effective scoping of your state which your connected component is interested in, if needed. This would likely impact the other equality checks as well, depending on your `mapStateToProps` function. From 405d39bcbcfab1c3182a5de3f215273b4995a1f2 Mon Sep 17 00:00:00 2001 From: jspurlin Date: Mon, 29 Aug 2022 09:36:29 -0700 Subject: [PATCH 6/7] Update connect.md remove extra space in connect.md --- docs/api/connect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/connect.md b/docs/api/connect.md index 112b728ce..9e42fb421 100644 --- a/docs/api/connect.md +++ b/docs/api/connect.md @@ -244,7 +244,7 @@ const areStatesEqual = (next, prev) => prev.entities.todos === next.entities.todos ``` -You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. Additionally, `areStatesEqual` provides `nextOwnProps` and `prevOwnProps` to allow for more effective scoping of your state which your connected component is interested in, if needed. +You may wish to override `areStatesEqual` if your `mapStateToProps` function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. Additionally, `areStatesEqual` provides `nextOwnProps` and `prevOwnProps` to allow for more effective scoping of your state which your connected component is interested in, if needed. This would likely impact the other equality checks as well, depending on your `mapStateToProps` function. From 527eb36f1af5d79e1c24ad14f88da70642c8d817 Mon Sep 17 00:00:00 2001 From: jspurlin Date: Thu, 1 Sep 2022 11:05:59 -0700 Subject: [PATCH 7/7] update type of actualChildProps to be more accurate --- src/components/connect.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/connect.tsx b/src/components/connect.tsx index be11ee4d1..963d72de9 100644 --- a/src/components/connect.tsx +++ b/src/components/connect.tsx @@ -701,7 +701,7 @@ function connect< notifyNestedSubs, ]) - let actualChildProps: uSES + let actualChildProps: Record try { actualChildProps = useSyncExternalStore(