From 9f92c5ec7e4adbc3895d8eb8bb86aaa314cc2ada Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Sun, 8 Dec 2024 15:47:05 +0400 Subject: [PATCH 1/3] Data: Include more details when shallow equality fails in 'useSelect' --- .../data/src/components/use-select/index.js | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index 15a3c88d2d5543..d61379b0425d13 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -19,6 +19,23 @@ import useAsyncMode from '../async-mode-provider/use-async-mode'; const renderQueue = createQueue(); +function warnOnUnstableReference( a, b ) { + let keys = []; + if ( a.constructor === Object && b.constructor === Object ) { + keys = Object.keys( a ).filter( ( k ) => a[ k ] !== b[ k ] ); + } else if ( Array.isArray( a ) && Array.isArray( b ) ) { + keys = [ ...a.keys() ].filter( ( i ) => a[ i ] !== b[ i ] ); + } + + // eslint-disable-next-line no-console + console.warn( + 'The `useSelect` hook returns different values when called with the same state and parameters.\n' + + 'This can lead to unnecessary re-renders and performance issues if not fixed.\n\n' + + 'Non-equal value keys: %s\n\n', + keys.join( ', ' ) + ); +} + /** * @typedef {import('../../types').StoreDescriptor} StoreDescriptor * @template {import('../../types').AnyConfig} C @@ -159,10 +176,7 @@ function Store( registry, suspense ) { if ( ! didWarnUnstableReference ) { const secondMapResult = mapSelect( select, registry ); if ( ! isShallowEqual( mapResult, secondMapResult ) ) { - // eslint-disable-next-line no-console - console.warn( - `The 'useSelect' hook returns different values when called with the same state and parameters. This can lead to unnecessary rerenders.` - ); + warnOnUnstableReference( mapResult, secondMapResult ); didWarnUnstableReference = true; } } From 39bc8c1c50fd7566f14207b3251c98fb9f1a43b8 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Mon, 9 Dec 2024 12:31:42 +0400 Subject: [PATCH 2/3] Simplify keys logic --- packages/data/src/components/use-select/index.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index d61379b0425d13..f2a3ab9826f781 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -20,13 +20,15 @@ import useAsyncMode from '../async-mode-provider/use-async-mode'; const renderQueue = createQueue(); function warnOnUnstableReference( a, b ) { - let keys = []; - if ( a.constructor === Object && b.constructor === Object ) { - keys = Object.keys( a ).filter( ( k ) => a[ k ] !== b[ k ] ); - } else if ( Array.isArray( a ) && Array.isArray( b ) ) { - keys = [ ...a.keys() ].filter( ( i ) => a[ i ] !== b[ i ] ); + if ( ! a && ! b ) { + return; } + const keys = + typeof a === 'object' && typeof b === 'object' + ? Object.keys( a ).filter( ( k ) => a[ k ] !== b[ k ] ) + : []; + // eslint-disable-next-line no-console console.warn( 'The `useSelect` hook returns different values when called with the same state and parameters.\n' + From b53a3a3597a161bf54c2210bea86eca577a9dae4 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Mon, 9 Dec 2024 13:16:51 +0400 Subject: [PATCH 3/3] Update early return condition --- packages/data/src/components/use-select/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index f2a3ab9826f781..6931743151773c 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -20,7 +20,7 @@ import useAsyncMode from '../async-mode-provider/use-async-mode'; const renderQueue = createQueue(); function warnOnUnstableReference( a, b ) { - if ( ! a && ! b ) { + if ( ! a || ! b ) { return; }