@wordpress/data 6.6.1 → 6.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/build/components/use-select/index.js +18 -20
- package/build/components/use-select/index.js.map +1 -1
- package/build-module/components/use-select/index.js +18 -20
- package/build-module/components/use-select/index.js.map +1 -1
- package/package.json +8 -8
- package/src/components/use-select/index.js +19 -19
- package/src/components/use-select/test/index.js +439 -265
package/CHANGELOG.md
CHANGED
|
@@ -132,11 +132,11 @@ function useSelect(mapSelect, deps) {
|
|
|
132
132
|
queue: true
|
|
133
133
|
}), [registry]);
|
|
134
134
|
const [, forceRender] = (0, _element.useReducer)(s => s + 1, 0);
|
|
135
|
+
const latestRegistry = (0, _element.useRef)(registry);
|
|
135
136
|
const latestMapSelect = (0, _element.useRef)();
|
|
136
137
|
const latestIsAsync = (0, _element.useRef)(isAsync);
|
|
137
138
|
const latestMapOutput = (0, _element.useRef)();
|
|
138
|
-
const latestMapOutputError = (0, _element.useRef)();
|
|
139
|
-
const isMountedAndNotUnsubscribing = (0, _element.useRef)(); // Keep track of the stores being selected in the _mapSelect function,
|
|
139
|
+
const latestMapOutputError = (0, _element.useRef)(); // Keep track of the stores being selected in the _mapSelect function,
|
|
140
140
|
// and only subscribe to those stores later.
|
|
141
141
|
|
|
142
142
|
const listeningStores = (0, _element.useRef)([]);
|
|
@@ -149,10 +149,11 @@ function useSelect(mapSelect, deps) {
|
|
|
149
149
|
|
|
150
150
|
if (_mapSelect) {
|
|
151
151
|
mapOutput = latestMapOutput.current;
|
|
152
|
+
const hasReplacedRegistry = latestRegistry.current !== registry;
|
|
152
153
|
const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;
|
|
153
154
|
const lastMapSelectFailed = !!latestMapOutputError.current;
|
|
154
155
|
|
|
155
|
-
if (hasReplacedMapSelect || lastMapSelectFailed) {
|
|
156
|
+
if (hasReplacedRegistry || hasReplacedMapSelect || lastMapSelectFailed) {
|
|
156
157
|
try {
|
|
157
158
|
mapOutput = wrapSelect(_mapSelect);
|
|
158
159
|
} catch (error) {
|
|
@@ -175,10 +176,10 @@ function useSelect(mapSelect, deps) {
|
|
|
175
176
|
return;
|
|
176
177
|
}
|
|
177
178
|
|
|
179
|
+
latestRegistry.current = registry;
|
|
178
180
|
latestMapSelect.current = _mapSelect;
|
|
179
181
|
latestMapOutput.current = mapOutput;
|
|
180
|
-
latestMapOutputError.current = undefined;
|
|
181
|
-
isMountedAndNotUnsubscribing.current = true; // This has to run after the other ref updates
|
|
182
|
+
latestMapOutputError.current = undefined; // This has to run after the other ref updates
|
|
182
183
|
// to avoid using stale values in the flushed
|
|
183
184
|
// callbacks or potentially overwriting a
|
|
184
185
|
// changed `latestMapOutput.current`.
|
|
@@ -194,21 +195,19 @@ function useSelect(mapSelect, deps) {
|
|
|
194
195
|
}
|
|
195
196
|
|
|
196
197
|
const onStoreChange = () => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const newMapOutput = wrapSelect(latestMapSelect.current);
|
|
200
|
-
|
|
201
|
-
if ((0, _isShallowEqual.default)(latestMapOutput.current, newMapOutput)) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
198
|
+
try {
|
|
199
|
+
const newMapOutput = wrapSelect(latestMapSelect.current);
|
|
204
200
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
latestMapOutputError.current = error;
|
|
201
|
+
if ((0, _isShallowEqual.default)(latestMapOutput.current, newMapOutput)) {
|
|
202
|
+
return;
|
|
208
203
|
}
|
|
209
204
|
|
|
210
|
-
|
|
205
|
+
latestMapOutput.current = newMapOutput;
|
|
206
|
+
} catch (error) {
|
|
207
|
+
latestMapOutputError.current = error;
|
|
211
208
|
}
|
|
209
|
+
|
|
210
|
+
forceRender();
|
|
212
211
|
};
|
|
213
212
|
|
|
214
213
|
const onChange = () => {
|
|
@@ -221,13 +220,12 @@ function useSelect(mapSelect, deps) {
|
|
|
221
220
|
// could be set.
|
|
222
221
|
|
|
223
222
|
|
|
224
|
-
|
|
223
|
+
onStoreChange();
|
|
225
224
|
const unsubscribers = listeningStores.current.map(storeName => registry.__unstableSubscribeStore(storeName, onChange));
|
|
226
225
|
return () => {
|
|
227
|
-
|
|
228
|
-
|
|
226
|
+
// The return value of the subscribe function could be undefined if the store is a custom generic store.
|
|
229
227
|
unsubscribers.forEach(unsubscribe => unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe());
|
|
230
|
-
renderQueue.
|
|
228
|
+
renderQueue.cancel(queueContext);
|
|
231
229
|
}; // If you're tempted to eliminate the spread dependencies below don't do it!
|
|
232
230
|
// We're passing these in from the calling function and want to make sure we're
|
|
233
231
|
// examining every individual value inside the `deps` array.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["noop","renderQueue","useSelect","mapSelect","deps","hasMappingFunction","callbackMapper","_mapSelect","registry","isAsync","queueContext","queue","forceRender","s","latestMapSelect","latestIsAsync","latestMapOutput","latestMapOutputError","isMountedAndNotUnsubscribing","listeningStores","wrapSelect","callback","__unstableMarkListeningStores","select","depsChangedFlag","mapOutput","current","hasReplacedMapSelect","lastMapSelectFailed","error","errorMessage","message","stack","console","undefined","flush","onStoreChange","newMapOutput","onChange","add","unsubscribers","map","storeName","__unstableSubscribeStore","forEach","unsubscribe"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { useMemoOne } from 'use-memo-one';\n\n/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport { useRef, useCallback, useMemo, useReducer } from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\nimport { useIsomorphicLayoutEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\nimport useAsyncMode from '../async-mode-provider/use-async-mode';\n\nconst noop = () => {};\nconst renderQueue = createQueue();\n\n/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */\n\n/**\n * Custom react hook for retrieving props from registered selectors.\n *\n * In general, this custom React hook follows the\n * [rules of hooks](https://reactjs.org/docs/hooks-rules.html).\n *\n * @param {Function|StoreDescriptor|string} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * implementing this hook. The function receives\n * the `registry.select` method on the first\n * argument and the `registry` on the second\n * argument.\n * When a store key is passed, all selectors for\n * the store will be returned. This is only meant\n * for usage of these selectors in event\n * callbacks, not for data needed to create the\n * element tree.\n * @param {Array} deps If provided, this memoizes the mapSelect so the\n * same `mapSelect` is invoked on every state\n * change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( 'my-shop' ).getPrice( 'hammer', currency )\n * }, [ currency ] );\n * return new Intl.NumberFormat( 'en-US', {\n * style: 'currency',\n * currency,\n * } ).format( price );\n * }\n *\n * // Rendered in the application:\n * // <HammerPriceDisplay currency=\"USD\" />\n * ```\n *\n * In the above example, when `HammerPriceDisplay` is rendered into an\n * application, the price will be retrieved from the store state using the\n * `mapSelect` callback on `useSelect`. If the currency prop changes then\n * any price in the state for that currency is retrieved. If the currency prop\n * doesn't change and other props are passed in that do change, the price will\n * not change because the dependency is just the currency.\n *\n * When data is only used in an event callback, the data should not be retrieved\n * on render, so it may be useful to get the selectors function instead.\n *\n * **Don't use `useSelect` this way when calling the selectors in the render\n * function because your component won't re-render on a data change.**\n *\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( 'my-shop' );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n *\n * @return {Function} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\tconst hasMappingFunction = 'function' === typeof mapSelect;\n\n\t// If we're recalling a store by its name or by\n\t// its descriptor then we won't be caching the\n\t// calls to `mapSelect` because we won't be calling it.\n\tif ( ! hasMappingFunction ) {\n\t\tdeps = [];\n\t}\n\n\t// Because of the \"rule of hooks\" we have to call `useCallback`\n\t// on every invocation whether or not we have a real function\n\t// for `mapSelect`. we'll create this intermediate variable to\n\t// fulfill that need and then reference it with our \"real\"\n\t// `_mapSelect` if we can.\n\tconst callbackMapper = useCallback(\n\t\thasMappingFunction ? mapSelect : noop,\n\t\tdeps\n\t);\n\tconst _mapSelect = hasMappingFunction ? callbackMapper : null;\n\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\t// React can sometimes clear the `useMemo` cache.\n\t// We use the cache-stable `useMemoOne` to avoid\n\t// losing queues.\n\tconst queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] );\n\tconst [ , forceRender ] = useReducer( ( s ) => s + 1, 0 );\n\n\tconst latestMapSelect = useRef();\n\tconst latestIsAsync = useRef( isAsync );\n\tconst latestMapOutput = useRef();\n\tconst latestMapOutputError = useRef();\n\tconst isMountedAndNotUnsubscribing = useRef();\n\n\t// Keep track of the stores being selected in the _mapSelect function,\n\t// and only subscribe to those stores later.\n\tconst listeningStores = useRef( [] );\n\tconst wrapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t() => callback( registry.select, registry ),\n\t\t\t\tlisteningStores\n\t\t\t),\n\t\t[ registry ]\n\t);\n\n\t// Generate a \"flag\" for used in the effect dependency array.\n\t// It's different than just using `mapSelect` since deps could be undefined,\n\t// in that case, we would still want to memoize it.\n\tconst depsChangedFlag = useMemo( () => ( {} ), deps || [] );\n\n\tlet mapOutput;\n\n\tif ( _mapSelect ) {\n\t\tmapOutput = latestMapOutput.current;\n\t\tconst hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;\n\t\tconst lastMapSelectFailed = !! latestMapOutputError.current;\n\n\t\tif ( hasReplacedMapSelect || lastMapSelectFailed ) {\n\t\t\ttry {\n\t\t\t\tmapOutput = wrapSelect( _mapSelect );\n\t\t\t} catch ( error ) {\n\t\t\t\tlet errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;\n\n\t\t\t\tif ( latestMapOutputError.current ) {\n\t\t\t\t\terrorMessage += `\\nThe error may be correlated with this previous error:\\n`;\n\t\t\t\t\terrorMessage += `${ latestMapOutputError.current.stack }\\n\\n`;\n\t\t\t\t\terrorMessage += 'Original stack trace:';\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error( errorMessage );\n\t\t\t}\n\t\t}\n\t}\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlatestMapSelect.current = _mapSelect;\n\t\tlatestMapOutput.current = mapOutput;\n\t\tlatestMapOutputError.current = undefined;\n\t\tisMountedAndNotUnsubscribing.current = true;\n\n\t\t// This has to run after the other ref updates\n\t\t// to avoid using stale values in the flushed\n\t\t// callbacks or potentially overwriting a\n\t\t// changed `latestMapOutput.current`.\n\t\tif ( latestIsAsync.current !== isAsync ) {\n\t\t\tlatestIsAsync.current = isAsync;\n\t\t\trenderQueue.flush( queueContext );\n\t\t}\n\t} );\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst onStoreChange = () => {\n\t\t\tif ( isMountedAndNotUnsubscribing.current ) {\n\t\t\t\ttry {\n\t\t\t\t\tconst newMapOutput = wrapSelect( latestMapSelect.current );\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tisShallowEqual( latestMapOutput.current, newMapOutput )\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tlatestMapOutput.current = newMapOutput;\n\t\t\t\t} catch ( error ) {\n\t\t\t\t\tlatestMapOutputError.current = error;\n\t\t\t\t}\n\t\t\t\tforceRender();\n\t\t\t}\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( latestIsAsync.current ) {\n\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t} else {\n\t\t\t\tonStoreChange();\n\t\t\t}\n\t\t};\n\n\t\t// Catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tonChange();\n\n\t\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.__unstableSubscribeStore( storeName, onChange )\n\t\t);\n\n\t\treturn () => {\n\t\t\tisMountedAndNotUnsubscribing.current = false;\n\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\tunsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );\n\t\t\trenderQueue.flush( queueContext );\n\t\t};\n\t\t// If you're tempted to eliminate the spread dependencies below don't do it!\n\t\t// We're passing these in from the calling function and want to make sure we're\n\t\t// examining every individual value inside the `deps` array.\n\t}, [ registry, wrapSelect, hasMappingFunction, depsChangedFlag ] );\n\n\treturn hasMappingFunction ? mapOutput : registry.select( mapSelect );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["noop","renderQueue","useSelect","mapSelect","deps","hasMappingFunction","callbackMapper","_mapSelect","registry","isAsync","queueContext","queue","forceRender","s","latestRegistry","latestMapSelect","latestIsAsync","latestMapOutput","latestMapOutputError","listeningStores","wrapSelect","callback","__unstableMarkListeningStores","select","depsChangedFlag","mapOutput","current","hasReplacedRegistry","hasReplacedMapSelect","lastMapSelectFailed","error","errorMessage","message","stack","console","undefined","flush","onStoreChange","newMapOutput","onChange","add","unsubscribers","map","storeName","__unstableSubscribeStore","forEach","unsubscribe","cancel"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { useMemoOne } from 'use-memo-one';\n\n/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport { useRef, useCallback, useMemo, useReducer } from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\nimport { useIsomorphicLayoutEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\nimport useAsyncMode from '../async-mode-provider/use-async-mode';\n\nconst noop = () => {};\nconst renderQueue = createQueue();\n\n/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */\n\n/**\n * Custom react hook for retrieving props from registered selectors.\n *\n * In general, this custom React hook follows the\n * [rules of hooks](https://reactjs.org/docs/hooks-rules.html).\n *\n * @param {Function|StoreDescriptor|string} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * implementing this hook. The function receives\n * the `registry.select` method on the first\n * argument and the `registry` on the second\n * argument.\n * When a store key is passed, all selectors for\n * the store will be returned. This is only meant\n * for usage of these selectors in event\n * callbacks, not for data needed to create the\n * element tree.\n * @param {Array} deps If provided, this memoizes the mapSelect so the\n * same `mapSelect` is invoked on every state\n * change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( 'my-shop' ).getPrice( 'hammer', currency )\n * }, [ currency ] );\n * return new Intl.NumberFormat( 'en-US', {\n * style: 'currency',\n * currency,\n * } ).format( price );\n * }\n *\n * // Rendered in the application:\n * // <HammerPriceDisplay currency=\"USD\" />\n * ```\n *\n * In the above example, when `HammerPriceDisplay` is rendered into an\n * application, the price will be retrieved from the store state using the\n * `mapSelect` callback on `useSelect`. If the currency prop changes then\n * any price in the state for that currency is retrieved. If the currency prop\n * doesn't change and other props are passed in that do change, the price will\n * not change because the dependency is just the currency.\n *\n * When data is only used in an event callback, the data should not be retrieved\n * on render, so it may be useful to get the selectors function instead.\n *\n * **Don't use `useSelect` this way when calling the selectors in the render\n * function because your component won't re-render on a data change.**\n *\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( 'my-shop' );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n *\n * @return {Function} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\tconst hasMappingFunction = 'function' === typeof mapSelect;\n\n\t// If we're recalling a store by its name or by\n\t// its descriptor then we won't be caching the\n\t// calls to `mapSelect` because we won't be calling it.\n\tif ( ! hasMappingFunction ) {\n\t\tdeps = [];\n\t}\n\n\t// Because of the \"rule of hooks\" we have to call `useCallback`\n\t// on every invocation whether or not we have a real function\n\t// for `mapSelect`. we'll create this intermediate variable to\n\t// fulfill that need and then reference it with our \"real\"\n\t// `_mapSelect` if we can.\n\tconst callbackMapper = useCallback(\n\t\thasMappingFunction ? mapSelect : noop,\n\t\tdeps\n\t);\n\tconst _mapSelect = hasMappingFunction ? callbackMapper : null;\n\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\t// React can sometimes clear the `useMemo` cache.\n\t// We use the cache-stable `useMemoOne` to avoid\n\t// losing queues.\n\tconst queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] );\n\tconst [ , forceRender ] = useReducer( ( s ) => s + 1, 0 );\n\n\tconst latestRegistry = useRef( registry );\n\tconst latestMapSelect = useRef();\n\tconst latestIsAsync = useRef( isAsync );\n\tconst latestMapOutput = useRef();\n\tconst latestMapOutputError = useRef();\n\n\t// Keep track of the stores being selected in the _mapSelect function,\n\t// and only subscribe to those stores later.\n\tconst listeningStores = useRef( [] );\n\tconst wrapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t() => callback( registry.select, registry ),\n\t\t\t\tlisteningStores\n\t\t\t),\n\t\t[ registry ]\n\t);\n\n\t// Generate a \"flag\" for used in the effect dependency array.\n\t// It's different than just using `mapSelect` since deps could be undefined,\n\t// in that case, we would still want to memoize it.\n\tconst depsChangedFlag = useMemo( () => ( {} ), deps || [] );\n\n\tlet mapOutput;\n\n\tif ( _mapSelect ) {\n\t\tmapOutput = latestMapOutput.current;\n\t\tconst hasReplacedRegistry = latestRegistry.current !== registry;\n\t\tconst hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;\n\t\tconst lastMapSelectFailed = !! latestMapOutputError.current;\n\n\t\tif (\n\t\t\thasReplacedRegistry ||\n\t\t\thasReplacedMapSelect ||\n\t\t\tlastMapSelectFailed\n\t\t) {\n\t\t\ttry {\n\t\t\t\tmapOutput = wrapSelect( _mapSelect );\n\t\t\t} catch ( error ) {\n\t\t\t\tlet errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;\n\n\t\t\t\tif ( latestMapOutputError.current ) {\n\t\t\t\t\terrorMessage += `\\nThe error may be correlated with this previous error:\\n`;\n\t\t\t\t\terrorMessage += `${ latestMapOutputError.current.stack }\\n\\n`;\n\t\t\t\t\terrorMessage += 'Original stack trace:';\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error( errorMessage );\n\t\t\t}\n\t\t}\n\t}\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlatestRegistry.current = registry;\n\t\tlatestMapSelect.current = _mapSelect;\n\t\tlatestMapOutput.current = mapOutput;\n\t\tlatestMapOutputError.current = undefined;\n\n\t\t// This has to run after the other ref updates\n\t\t// to avoid using stale values in the flushed\n\t\t// callbacks or potentially overwriting a\n\t\t// changed `latestMapOutput.current`.\n\t\tif ( latestIsAsync.current !== isAsync ) {\n\t\t\tlatestIsAsync.current = isAsync;\n\t\t\trenderQueue.flush( queueContext );\n\t\t}\n\t} );\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst onStoreChange = () => {\n\t\t\ttry {\n\t\t\t\tconst newMapOutput = wrapSelect( latestMapSelect.current );\n\n\t\t\t\tif ( isShallowEqual( latestMapOutput.current, newMapOutput ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlatestMapOutput.current = newMapOutput;\n\t\t\t} catch ( error ) {\n\t\t\t\tlatestMapOutputError.current = error;\n\t\t\t}\n\t\t\tforceRender();\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( latestIsAsync.current ) {\n\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t} else {\n\t\t\t\tonStoreChange();\n\t\t\t}\n\t\t};\n\n\t\t// Catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tonStoreChange();\n\n\t\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.__unstableSubscribeStore( storeName, onChange )\n\t\t);\n\n\t\treturn () => {\n\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\tunsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );\n\t\t\trenderQueue.cancel( queueContext );\n\t\t};\n\t\t// If you're tempted to eliminate the spread dependencies below don't do it!\n\t\t// We're passing these in from the calling function and want to make sure we're\n\t\t// examining every individual value inside the `deps` array.\n\t}, [ registry, wrapSelect, hasMappingFunction, depsChangedFlag ] );\n\n\treturn hasMappingFunction ? mapOutput : registry.select( mapSelect );\n}\n"]}
|
|
@@ -117,11 +117,11 @@ export default function useSelect(mapSelect, deps) {
|
|
|
117
117
|
queue: true
|
|
118
118
|
}), [registry]);
|
|
119
119
|
const [, forceRender] = useReducer(s => s + 1, 0);
|
|
120
|
+
const latestRegistry = useRef(registry);
|
|
120
121
|
const latestMapSelect = useRef();
|
|
121
122
|
const latestIsAsync = useRef(isAsync);
|
|
122
123
|
const latestMapOutput = useRef();
|
|
123
|
-
const latestMapOutputError = useRef();
|
|
124
|
-
const isMountedAndNotUnsubscribing = useRef(); // Keep track of the stores being selected in the _mapSelect function,
|
|
124
|
+
const latestMapOutputError = useRef(); // Keep track of the stores being selected in the _mapSelect function,
|
|
125
125
|
// and only subscribe to those stores later.
|
|
126
126
|
|
|
127
127
|
const listeningStores = useRef([]);
|
|
@@ -134,10 +134,11 @@ export default function useSelect(mapSelect, deps) {
|
|
|
134
134
|
|
|
135
135
|
if (_mapSelect) {
|
|
136
136
|
mapOutput = latestMapOutput.current;
|
|
137
|
+
const hasReplacedRegistry = latestRegistry.current !== registry;
|
|
137
138
|
const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;
|
|
138
139
|
const lastMapSelectFailed = !!latestMapOutputError.current;
|
|
139
140
|
|
|
140
|
-
if (hasReplacedMapSelect || lastMapSelectFailed) {
|
|
141
|
+
if (hasReplacedRegistry || hasReplacedMapSelect || lastMapSelectFailed) {
|
|
141
142
|
try {
|
|
142
143
|
mapOutput = wrapSelect(_mapSelect);
|
|
143
144
|
} catch (error) {
|
|
@@ -160,10 +161,10 @@ export default function useSelect(mapSelect, deps) {
|
|
|
160
161
|
return;
|
|
161
162
|
}
|
|
162
163
|
|
|
164
|
+
latestRegistry.current = registry;
|
|
163
165
|
latestMapSelect.current = _mapSelect;
|
|
164
166
|
latestMapOutput.current = mapOutput;
|
|
165
|
-
latestMapOutputError.current = undefined;
|
|
166
|
-
isMountedAndNotUnsubscribing.current = true; // This has to run after the other ref updates
|
|
167
|
+
latestMapOutputError.current = undefined; // This has to run after the other ref updates
|
|
167
168
|
// to avoid using stale values in the flushed
|
|
168
169
|
// callbacks or potentially overwriting a
|
|
169
170
|
// changed `latestMapOutput.current`.
|
|
@@ -179,21 +180,19 @@ export default function useSelect(mapSelect, deps) {
|
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
const onStoreChange = () => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const newMapOutput = wrapSelect(latestMapSelect.current);
|
|
185
|
-
|
|
186
|
-
if (isShallowEqual(latestMapOutput.current, newMapOutput)) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
183
|
+
try {
|
|
184
|
+
const newMapOutput = wrapSelect(latestMapSelect.current);
|
|
189
185
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
latestMapOutputError.current = error;
|
|
186
|
+
if (isShallowEqual(latestMapOutput.current, newMapOutput)) {
|
|
187
|
+
return;
|
|
193
188
|
}
|
|
194
189
|
|
|
195
|
-
|
|
190
|
+
latestMapOutput.current = newMapOutput;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
latestMapOutputError.current = error;
|
|
196
193
|
}
|
|
194
|
+
|
|
195
|
+
forceRender();
|
|
197
196
|
};
|
|
198
197
|
|
|
199
198
|
const onChange = () => {
|
|
@@ -206,13 +205,12 @@ export default function useSelect(mapSelect, deps) {
|
|
|
206
205
|
// could be set.
|
|
207
206
|
|
|
208
207
|
|
|
209
|
-
|
|
208
|
+
onStoreChange();
|
|
210
209
|
const unsubscribers = listeningStores.current.map(storeName => registry.__unstableSubscribeStore(storeName, onChange));
|
|
211
210
|
return () => {
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
// The return value of the subscribe function could be undefined if the store is a custom generic store.
|
|
214
212
|
unsubscribers.forEach(unsubscribe => unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe());
|
|
215
|
-
renderQueue.
|
|
213
|
+
renderQueue.cancel(queueContext);
|
|
216
214
|
}; // If you're tempted to eliminate the spread dependencies below don't do it!
|
|
217
215
|
// We're passing these in from the calling function and want to make sure we're
|
|
218
216
|
// examining every individual value inside the `deps` array.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["useMemoOne","createQueue","useRef","useCallback","useMemo","useReducer","isShallowEqual","useIsomorphicLayoutEffect","useRegistry","useAsyncMode","noop","renderQueue","useSelect","mapSelect","deps","hasMappingFunction","callbackMapper","_mapSelect","registry","isAsync","queueContext","queue","forceRender","s","latestMapSelect","latestIsAsync","latestMapOutput","latestMapOutputError","isMountedAndNotUnsubscribing","listeningStores","wrapSelect","callback","__unstableMarkListeningStores","select","depsChangedFlag","mapOutput","current","hasReplacedMapSelect","lastMapSelectFailed","error","errorMessage","message","stack","console","undefined","flush","onStoreChange","newMapOutput","onChange","add","unsubscribers","map","storeName","__unstableSubscribeStore","forEach","unsubscribe"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { useMemoOne } from 'use-memo-one';\n\n/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport { useRef, useCallback, useMemo, useReducer } from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\nimport { useIsomorphicLayoutEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\nimport useAsyncMode from '../async-mode-provider/use-async-mode';\n\nconst noop = () => {};\nconst renderQueue = createQueue();\n\n/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */\n\n/**\n * Custom react hook for retrieving props from registered selectors.\n *\n * In general, this custom React hook follows the\n * [rules of hooks](https://reactjs.org/docs/hooks-rules.html).\n *\n * @param {Function|StoreDescriptor|string} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * implementing this hook. The function receives\n * the `registry.select` method on the first\n * argument and the `registry` on the second\n * argument.\n * When a store key is passed, all selectors for\n * the store will be returned. This is only meant\n * for usage of these selectors in event\n * callbacks, not for data needed to create the\n * element tree.\n * @param {Array} deps If provided, this memoizes the mapSelect so the\n * same `mapSelect` is invoked on every state\n * change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( 'my-shop' ).getPrice( 'hammer', currency )\n * }, [ currency ] );\n * return new Intl.NumberFormat( 'en-US', {\n * style: 'currency',\n * currency,\n * } ).format( price );\n * }\n *\n * // Rendered in the application:\n * // <HammerPriceDisplay currency=\"USD\" />\n * ```\n *\n * In the above example, when `HammerPriceDisplay` is rendered into an\n * application, the price will be retrieved from the store state using the\n * `mapSelect` callback on `useSelect`. If the currency prop changes then\n * any price in the state for that currency is retrieved. If the currency prop\n * doesn't change and other props are passed in that do change, the price will\n * not change because the dependency is just the currency.\n *\n * When data is only used in an event callback, the data should not be retrieved\n * on render, so it may be useful to get the selectors function instead.\n *\n * **Don't use `useSelect` this way when calling the selectors in the render\n * function because your component won't re-render on a data change.**\n *\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( 'my-shop' );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n *\n * @return {Function} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\tconst hasMappingFunction = 'function' === typeof mapSelect;\n\n\t// If we're recalling a store by its name or by\n\t// its descriptor then we won't be caching the\n\t// calls to `mapSelect` because we won't be calling it.\n\tif ( ! hasMappingFunction ) {\n\t\tdeps = [];\n\t}\n\n\t// Because of the \"rule of hooks\" we have to call `useCallback`\n\t// on every invocation whether or not we have a real function\n\t// for `mapSelect`. we'll create this intermediate variable to\n\t// fulfill that need and then reference it with our \"real\"\n\t// `_mapSelect` if we can.\n\tconst callbackMapper = useCallback(\n\t\thasMappingFunction ? mapSelect : noop,\n\t\tdeps\n\t);\n\tconst _mapSelect = hasMappingFunction ? callbackMapper : null;\n\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\t// React can sometimes clear the `useMemo` cache.\n\t// We use the cache-stable `useMemoOne` to avoid\n\t// losing queues.\n\tconst queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] );\n\tconst [ , forceRender ] = useReducer( ( s ) => s + 1, 0 );\n\n\tconst latestMapSelect = useRef();\n\tconst latestIsAsync = useRef( isAsync );\n\tconst latestMapOutput = useRef();\n\tconst latestMapOutputError = useRef();\n\tconst isMountedAndNotUnsubscribing = useRef();\n\n\t// Keep track of the stores being selected in the _mapSelect function,\n\t// and only subscribe to those stores later.\n\tconst listeningStores = useRef( [] );\n\tconst wrapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t() => callback( registry.select, registry ),\n\t\t\t\tlisteningStores\n\t\t\t),\n\t\t[ registry ]\n\t);\n\n\t// Generate a \"flag\" for used in the effect dependency array.\n\t// It's different than just using `mapSelect` since deps could be undefined,\n\t// in that case, we would still want to memoize it.\n\tconst depsChangedFlag = useMemo( () => ( {} ), deps || [] );\n\n\tlet mapOutput;\n\n\tif ( _mapSelect ) {\n\t\tmapOutput = latestMapOutput.current;\n\t\tconst hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;\n\t\tconst lastMapSelectFailed = !! latestMapOutputError.current;\n\n\t\tif ( hasReplacedMapSelect || lastMapSelectFailed ) {\n\t\t\ttry {\n\t\t\t\tmapOutput = wrapSelect( _mapSelect );\n\t\t\t} catch ( error ) {\n\t\t\t\tlet errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;\n\n\t\t\t\tif ( latestMapOutputError.current ) {\n\t\t\t\t\terrorMessage += `\\nThe error may be correlated with this previous error:\\n`;\n\t\t\t\t\terrorMessage += `${ latestMapOutputError.current.stack }\\n\\n`;\n\t\t\t\t\terrorMessage += 'Original stack trace:';\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error( errorMessage );\n\t\t\t}\n\t\t}\n\t}\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlatestMapSelect.current = _mapSelect;\n\t\tlatestMapOutput.current = mapOutput;\n\t\tlatestMapOutputError.current = undefined;\n\t\tisMountedAndNotUnsubscribing.current = true;\n\n\t\t// This has to run after the other ref updates\n\t\t// to avoid using stale values in the flushed\n\t\t// callbacks or potentially overwriting a\n\t\t// changed `latestMapOutput.current`.\n\t\tif ( latestIsAsync.current !== isAsync ) {\n\t\t\tlatestIsAsync.current = isAsync;\n\t\t\trenderQueue.flush( queueContext );\n\t\t}\n\t} );\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst onStoreChange = () => {\n\t\t\tif ( isMountedAndNotUnsubscribing.current ) {\n\t\t\t\ttry {\n\t\t\t\t\tconst newMapOutput = wrapSelect( latestMapSelect.current );\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tisShallowEqual( latestMapOutput.current, newMapOutput )\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tlatestMapOutput.current = newMapOutput;\n\t\t\t\t} catch ( error ) {\n\t\t\t\t\tlatestMapOutputError.current = error;\n\t\t\t\t}\n\t\t\t\tforceRender();\n\t\t\t}\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( latestIsAsync.current ) {\n\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t} else {\n\t\t\t\tonStoreChange();\n\t\t\t}\n\t\t};\n\n\t\t// Catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tonChange();\n\n\t\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.__unstableSubscribeStore( storeName, onChange )\n\t\t);\n\n\t\treturn () => {\n\t\t\tisMountedAndNotUnsubscribing.current = false;\n\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\tunsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );\n\t\t\trenderQueue.flush( queueContext );\n\t\t};\n\t\t// If you're tempted to eliminate the spread dependencies below don't do it!\n\t\t// We're passing these in from the calling function and want to make sure we're\n\t\t// examining every individual value inside the `deps` array.\n\t}, [ registry, wrapSelect, hasMappingFunction, depsChangedFlag ] );\n\n\treturn hasMappingFunction ? mapOutput : registry.select( mapSelect );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["useMemoOne","createQueue","useRef","useCallback","useMemo","useReducer","isShallowEqual","useIsomorphicLayoutEffect","useRegistry","useAsyncMode","noop","renderQueue","useSelect","mapSelect","deps","hasMappingFunction","callbackMapper","_mapSelect","registry","isAsync","queueContext","queue","forceRender","s","latestRegistry","latestMapSelect","latestIsAsync","latestMapOutput","latestMapOutputError","listeningStores","wrapSelect","callback","__unstableMarkListeningStores","select","depsChangedFlag","mapOutput","current","hasReplacedRegistry","hasReplacedMapSelect","lastMapSelectFailed","error","errorMessage","message","stack","console","undefined","flush","onStoreChange","newMapOutput","onChange","add","unsubscribers","map","storeName","__unstableSubscribeStore","forEach","unsubscribe","cancel"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { useMemoOne } from 'use-memo-one';\n\n/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport { useRef, useCallback, useMemo, useReducer } from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\nimport { useIsomorphicLayoutEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\nimport useAsyncMode from '../async-mode-provider/use-async-mode';\n\nconst noop = () => {};\nconst renderQueue = createQueue();\n\n/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */\n\n/**\n * Custom react hook for retrieving props from registered selectors.\n *\n * In general, this custom React hook follows the\n * [rules of hooks](https://reactjs.org/docs/hooks-rules.html).\n *\n * @param {Function|StoreDescriptor|string} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * implementing this hook. The function receives\n * the `registry.select` method on the first\n * argument and the `registry` on the second\n * argument.\n * When a store key is passed, all selectors for\n * the store will be returned. This is only meant\n * for usage of these selectors in event\n * callbacks, not for data needed to create the\n * element tree.\n * @param {Array} deps If provided, this memoizes the mapSelect so the\n * same `mapSelect` is invoked on every state\n * change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( 'my-shop' ).getPrice( 'hammer', currency )\n * }, [ currency ] );\n * return new Intl.NumberFormat( 'en-US', {\n * style: 'currency',\n * currency,\n * } ).format( price );\n * }\n *\n * // Rendered in the application:\n * // <HammerPriceDisplay currency=\"USD\" />\n * ```\n *\n * In the above example, when `HammerPriceDisplay` is rendered into an\n * application, the price will be retrieved from the store state using the\n * `mapSelect` callback on `useSelect`. If the currency prop changes then\n * any price in the state for that currency is retrieved. If the currency prop\n * doesn't change and other props are passed in that do change, the price will\n * not change because the dependency is just the currency.\n *\n * When data is only used in an event callback, the data should not be retrieved\n * on render, so it may be useful to get the selectors function instead.\n *\n * **Don't use `useSelect` this way when calling the selectors in the render\n * function because your component won't re-render on a data change.**\n *\n * ```js\n * import { useSelect } from '@wordpress/data';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( 'my-shop' );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n *\n * @return {Function} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\tconst hasMappingFunction = 'function' === typeof mapSelect;\n\n\t// If we're recalling a store by its name or by\n\t// its descriptor then we won't be caching the\n\t// calls to `mapSelect` because we won't be calling it.\n\tif ( ! hasMappingFunction ) {\n\t\tdeps = [];\n\t}\n\n\t// Because of the \"rule of hooks\" we have to call `useCallback`\n\t// on every invocation whether or not we have a real function\n\t// for `mapSelect`. we'll create this intermediate variable to\n\t// fulfill that need and then reference it with our \"real\"\n\t// `_mapSelect` if we can.\n\tconst callbackMapper = useCallback(\n\t\thasMappingFunction ? mapSelect : noop,\n\t\tdeps\n\t);\n\tconst _mapSelect = hasMappingFunction ? callbackMapper : null;\n\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\t// React can sometimes clear the `useMemo` cache.\n\t// We use the cache-stable `useMemoOne` to avoid\n\t// losing queues.\n\tconst queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] );\n\tconst [ , forceRender ] = useReducer( ( s ) => s + 1, 0 );\n\n\tconst latestRegistry = useRef( registry );\n\tconst latestMapSelect = useRef();\n\tconst latestIsAsync = useRef( isAsync );\n\tconst latestMapOutput = useRef();\n\tconst latestMapOutputError = useRef();\n\n\t// Keep track of the stores being selected in the _mapSelect function,\n\t// and only subscribe to those stores later.\n\tconst listeningStores = useRef( [] );\n\tconst wrapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t() => callback( registry.select, registry ),\n\t\t\t\tlisteningStores\n\t\t\t),\n\t\t[ registry ]\n\t);\n\n\t// Generate a \"flag\" for used in the effect dependency array.\n\t// It's different than just using `mapSelect` since deps could be undefined,\n\t// in that case, we would still want to memoize it.\n\tconst depsChangedFlag = useMemo( () => ( {} ), deps || [] );\n\n\tlet mapOutput;\n\n\tif ( _mapSelect ) {\n\t\tmapOutput = latestMapOutput.current;\n\t\tconst hasReplacedRegistry = latestRegistry.current !== registry;\n\t\tconst hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;\n\t\tconst lastMapSelectFailed = !! latestMapOutputError.current;\n\n\t\tif (\n\t\t\thasReplacedRegistry ||\n\t\t\thasReplacedMapSelect ||\n\t\t\tlastMapSelectFailed\n\t\t) {\n\t\t\ttry {\n\t\t\t\tmapOutput = wrapSelect( _mapSelect );\n\t\t\t} catch ( error ) {\n\t\t\t\tlet errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;\n\n\t\t\t\tif ( latestMapOutputError.current ) {\n\t\t\t\t\terrorMessage += `\\nThe error may be correlated with this previous error:\\n`;\n\t\t\t\t\terrorMessage += `${ latestMapOutputError.current.stack }\\n\\n`;\n\t\t\t\t\terrorMessage += 'Original stack trace:';\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error( errorMessage );\n\t\t\t}\n\t\t}\n\t}\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlatestRegistry.current = registry;\n\t\tlatestMapSelect.current = _mapSelect;\n\t\tlatestMapOutput.current = mapOutput;\n\t\tlatestMapOutputError.current = undefined;\n\n\t\t// This has to run after the other ref updates\n\t\t// to avoid using stale values in the flushed\n\t\t// callbacks or potentially overwriting a\n\t\t// changed `latestMapOutput.current`.\n\t\tif ( latestIsAsync.current !== isAsync ) {\n\t\t\tlatestIsAsync.current = isAsync;\n\t\t\trenderQueue.flush( queueContext );\n\t\t}\n\t} );\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst onStoreChange = () => {\n\t\t\ttry {\n\t\t\t\tconst newMapOutput = wrapSelect( latestMapSelect.current );\n\n\t\t\t\tif ( isShallowEqual( latestMapOutput.current, newMapOutput ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlatestMapOutput.current = newMapOutput;\n\t\t\t} catch ( error ) {\n\t\t\t\tlatestMapOutputError.current = error;\n\t\t\t}\n\t\t\tforceRender();\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( latestIsAsync.current ) {\n\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t} else {\n\t\t\t\tonStoreChange();\n\t\t\t}\n\t\t};\n\n\t\t// Catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tonStoreChange();\n\n\t\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.__unstableSubscribeStore( storeName, onChange )\n\t\t);\n\n\t\treturn () => {\n\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\tunsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );\n\t\t\trenderQueue.cancel( queueContext );\n\t\t};\n\t\t// If you're tempted to eliminate the spread dependencies below don't do it!\n\t\t// We're passing these in from the calling function and want to make sure we're\n\t\t// examining every individual value inside the `deps` array.\n\t}, [ registry, wrapSelect, hasMappingFunction, depsChangedFlag ] );\n\n\treturn hasMappingFunction ? mapOutput : registry.select( mapSelect );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/data",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.0",
|
|
4
4
|
"description": "Data module for WordPress.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@babel/runtime": "^7.16.0",
|
|
31
|
-
"@wordpress/compose": "^5.
|
|
32
|
-
"@wordpress/deprecated": "^3.
|
|
33
|
-
"@wordpress/element": "^4.
|
|
34
|
-
"@wordpress/is-shallow-equal": "^4.
|
|
35
|
-
"@wordpress/priority-queue": "^2.
|
|
36
|
-
"@wordpress/redux-routine": "^4.
|
|
31
|
+
"@wordpress/compose": "^5.5.0",
|
|
32
|
+
"@wordpress/deprecated": "^3.7.0",
|
|
33
|
+
"@wordpress/element": "^4.5.0",
|
|
34
|
+
"@wordpress/is-shallow-equal": "^4.7.0",
|
|
35
|
+
"@wordpress/priority-queue": "^2.7.0",
|
|
36
|
+
"@wordpress/redux-routine": "^4.7.0",
|
|
37
37
|
"equivalent-key-map": "^0.2.2",
|
|
38
38
|
"is-promise": "^4.0.0",
|
|
39
39
|
"lodash": "^4.17.21",
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "1ba52312b56db563df2d8d4fba5b00613fb46d8c"
|
|
51
51
|
}
|
|
@@ -118,11 +118,11 @@ export default function useSelect( mapSelect, deps ) {
|
|
|
118
118
|
const queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] );
|
|
119
119
|
const [ , forceRender ] = useReducer( ( s ) => s + 1, 0 );
|
|
120
120
|
|
|
121
|
+
const latestRegistry = useRef( registry );
|
|
121
122
|
const latestMapSelect = useRef();
|
|
122
123
|
const latestIsAsync = useRef( isAsync );
|
|
123
124
|
const latestMapOutput = useRef();
|
|
124
125
|
const latestMapOutputError = useRef();
|
|
125
|
-
const isMountedAndNotUnsubscribing = useRef();
|
|
126
126
|
|
|
127
127
|
// Keep track of the stores being selected in the _mapSelect function,
|
|
128
128
|
// and only subscribe to those stores later.
|
|
@@ -145,10 +145,15 @@ export default function useSelect( mapSelect, deps ) {
|
|
|
145
145
|
|
|
146
146
|
if ( _mapSelect ) {
|
|
147
147
|
mapOutput = latestMapOutput.current;
|
|
148
|
+
const hasReplacedRegistry = latestRegistry.current !== registry;
|
|
148
149
|
const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;
|
|
149
150
|
const lastMapSelectFailed = !! latestMapOutputError.current;
|
|
150
151
|
|
|
151
|
-
if (
|
|
152
|
+
if (
|
|
153
|
+
hasReplacedRegistry ||
|
|
154
|
+
hasReplacedMapSelect ||
|
|
155
|
+
lastMapSelectFailed
|
|
156
|
+
) {
|
|
152
157
|
try {
|
|
153
158
|
mapOutput = wrapSelect( _mapSelect );
|
|
154
159
|
} catch ( error ) {
|
|
@@ -171,10 +176,10 @@ export default function useSelect( mapSelect, deps ) {
|
|
|
171
176
|
return;
|
|
172
177
|
}
|
|
173
178
|
|
|
179
|
+
latestRegistry.current = registry;
|
|
174
180
|
latestMapSelect.current = _mapSelect;
|
|
175
181
|
latestMapOutput.current = mapOutput;
|
|
176
182
|
latestMapOutputError.current = undefined;
|
|
177
|
-
isMountedAndNotUnsubscribing.current = true;
|
|
178
183
|
|
|
179
184
|
// This has to run after the other ref updates
|
|
180
185
|
// to avoid using stale values in the flushed
|
|
@@ -192,21 +197,17 @@ export default function useSelect( mapSelect, deps ) {
|
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
const onStoreChange = () => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
isShallowEqual( latestMapOutput.current, newMapOutput )
|
|
201
|
-
) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
latestMapOutput.current = newMapOutput;
|
|
205
|
-
} catch ( error ) {
|
|
206
|
-
latestMapOutputError.current = error;
|
|
200
|
+
try {
|
|
201
|
+
const newMapOutput = wrapSelect( latestMapSelect.current );
|
|
202
|
+
|
|
203
|
+
if ( isShallowEqual( latestMapOutput.current, newMapOutput ) ) {
|
|
204
|
+
return;
|
|
207
205
|
}
|
|
208
|
-
|
|
206
|
+
latestMapOutput.current = newMapOutput;
|
|
207
|
+
} catch ( error ) {
|
|
208
|
+
latestMapOutputError.current = error;
|
|
209
209
|
}
|
|
210
|
+
forceRender();
|
|
210
211
|
};
|
|
211
212
|
|
|
212
213
|
const onChange = () => {
|
|
@@ -219,17 +220,16 @@ export default function useSelect( mapSelect, deps ) {
|
|
|
219
220
|
|
|
220
221
|
// Catch any possible state changes during mount before the subscription
|
|
221
222
|
// could be set.
|
|
222
|
-
|
|
223
|
+
onStoreChange();
|
|
223
224
|
|
|
224
225
|
const unsubscribers = listeningStores.current.map( ( storeName ) =>
|
|
225
226
|
registry.__unstableSubscribeStore( storeName, onChange )
|
|
226
227
|
);
|
|
227
228
|
|
|
228
229
|
return () => {
|
|
229
|
-
isMountedAndNotUnsubscribing.current = false;
|
|
230
230
|
// The return value of the subscribe function could be undefined if the store is a custom generic store.
|
|
231
231
|
unsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );
|
|
232
|
-
renderQueue.
|
|
232
|
+
renderQueue.cancel( queueContext );
|
|
233
233
|
};
|
|
234
234
|
// If you're tempted to eliminate the spread dependencies below don't do it!
|
|
235
235
|
// We're passing these in from the calling function and want to make sure we're
|