From ba9c8d1eaedda95a5df44fa3e3f61a1ef0dc0237 Mon Sep 17 00:00:00 2001 From: epiqueras Date: Fri, 20 Dec 2019 19:18:56 -0300 Subject: [PATCH 1/3] Use Select: Fix render queue issues. --- package-lock.json | 12 ++++++--- packages/data/package.json | 3 ++- .../data/src/components/use-select/index.js | 26 +++++++++++++------ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 83d32e847a5b0e..faa74e088c6cc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9691,7 +9691,8 @@ "lodash": "^4.17.15", "memize": "^1.0.5", "redux": "^4.0.0", - "turbo-combine-reducers": "^1.0.2" + "turbo-combine-reducers": "^1.0.2", + "use-memo-one": "^1.1.1" } }, "@wordpress/data-controls": { @@ -24684,7 +24685,7 @@ "dependencies": { "clone-deep": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "resolved": "http://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", "dev": true, "requires": { @@ -24718,7 +24719,7 @@ "dependencies": { "kind-of": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", "dev": true, "requires": { @@ -36579,6 +36580,11 @@ "integrity": "sha512-C3nvxh0ZpaOxs9RCnWwAJ+7bJPwQI8LHF71LzbQ3BvzH5XkdtlkMadqElGevg5bYBDFip4sAnD4m06zAKebg1w==", "dev": true }, + "use-memo-one": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz", + "integrity": "sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ==" + }, "use-sidecar": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.2.tgz", diff --git a/packages/data/package.json b/packages/data/package.json index b246b0cf500b3e..375c98db1d086c 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -34,7 +34,8 @@ "lodash": "^4.17.15", "memize": "^1.0.5", "redux": "^4.0.0", - "turbo-combine-reducers": "^1.0.2" + "turbo-combine-reducers": "^1.0.2", + "use-memo-one": "^1.1.1" }, "publishConfig": { "access": "public" diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index 1ea5619477b7b3..8ded2809fda124 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import { useMemoOne } from 'use-memo-one'; + /** * WordPress dependencies */ @@ -5,7 +10,6 @@ import { createQueue } from '@wordpress/priority-queue'; import { useLayoutEffect, useRef, - useMemo, useCallback, useEffect, useReducer, @@ -78,7 +82,10 @@ export default function useSelect( _mapSelect, deps ) { const mapSelect = useCallback( _mapSelect, deps ); const registry = useRegistry(); const isAsync = useAsyncMode(); - const queueContext = useMemo( () => ( { queue: true } ), [ registry ] ); + // React can sometimes clear the `useMemo` cache. + // We use the cache-stable `useMemoOne` to avoid + // losing queues. + const queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] ); const [ , forceRender ] = useReducer( ( s ) => s + 1, 0 ); const latestMapSelect = useRef(); @@ -96,9 +103,7 @@ export default function useSelect( _mapSelect, deps ) { mapOutput = latestMapOutput.current; } } catch ( error ) { - let errorMessage = `An error occurred while running 'mapSelect': ${ - error.message - }`; + let errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`; if ( latestMapOutputError.current ) { errorMessage += `\nThe error may be correlated with this previous error:\n`; @@ -111,13 +116,18 @@ export default function useSelect( _mapSelect, deps ) { useIsomorphicLayoutEffect( () => { latestMapSelect.current = mapSelect; + latestMapOutput.current = mapOutput; + latestMapOutputError.current = undefined; + isMounted.current = true; + + // This has to run after the other ref updates + // to avoid using stale values in the flushed + // callbacks or potentially overwriting a + // changed `latestMapOutput.current`. if ( latestIsAsync.current !== isAsync ) { latestIsAsync.current = isAsync; renderQueue.flush( queueContext ); } - latestMapOutput.current = mapOutput; - latestMapOutputError.current = undefined; - isMounted.current = true; } ); useIsomorphicLayoutEffect( () => { From 21c2e24e06415b2b02e60cc1cef42a6f89f9daaa Mon Sep 17 00:00:00 2001 From: epiqueras Date: Fri, 20 Dec 2019 19:20:34 -0300 Subject: [PATCH 2/3] Use Select: Make `isMounted` more informative. --- packages/data/src/components/use-select/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index 8ded2809fda124..97b8e207dd11dc 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -92,7 +92,7 @@ export default function useSelect( _mapSelect, deps ) { const latestIsAsync = useRef( isAsync ); const latestMapOutput = useRef(); const latestMapOutputError = useRef(); - const isMounted = useRef(); + const isMountedAndNotUnsubscribing = useRef(); let mapOutput; @@ -118,7 +118,7 @@ export default function useSelect( _mapSelect, deps ) { latestMapSelect.current = mapSelect; latestMapOutput.current = mapOutput; latestMapOutputError.current = undefined; - isMounted.current = true; + isMountedAndNotUnsubscribing.current = true; // This has to run after the other ref updates // to avoid using stale values in the flushed @@ -132,7 +132,7 @@ export default function useSelect( _mapSelect, deps ) { useIsomorphicLayoutEffect( () => { const onStoreChange = () => { - if ( isMounted.current ) { + if ( isMountedAndNotUnsubscribing.current ) { try { const newMapOutput = latestMapSelect.current( registry.select, @@ -166,7 +166,7 @@ export default function useSelect( _mapSelect, deps ) { } ); return () => { - isMounted.current = false; + isMountedAndNotUnsubscribing.current = false; unsubscribe(); renderQueue.flush( queueContext ); }; From c71271838ef322bf6276dfcf79ce406e62c07766 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 17 Jan 2020 12:48:32 -0500 Subject: [PATCH 3/3] Framework: Reset lockfile changes to dependencies --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index faa74e088c6cc6..f7c0903b364bd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24685,7 +24685,7 @@ "dependencies": { "clone-deep": { "version": "0.2.4", - "resolved": "http://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", "dev": true, "requires": { @@ -24719,7 +24719,7 @@ "dependencies": { "kind-of": { "version": "2.0.1", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", "dev": true, "requires": {