@wordpress/data 6.1.4 → 6.1.6-next.33ec3857e2.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +68 -68
  3. package/build/components/use-dispatch/use-dispatch.js +8 -8
  4. package/build/components/use-dispatch/use-dispatch.js.map +1 -1
  5. package/build/components/use-select/index.js +58 -43
  6. package/build/components/use-select/index.js.map +1 -1
  7. package/build/controls.js +16 -16
  8. package/build/controls.js.map +1 -1
  9. package/build/index.js +14 -14
  10. package/build/index.js.map +1 -1
  11. package/build/redux-store/index.js +15 -15
  12. package/build/redux-store/index.js.map +1 -1
  13. package/build/registry.js +78 -68
  14. package/build/registry.js.map +1 -1
  15. package/build/resolvers-cache-middleware.js +5 -3
  16. package/build/resolvers-cache-middleware.js.map +1 -1
  17. package/build/store/index.js +42 -43
  18. package/build/store/index.js.map +1 -1
  19. package/build/utils/emitter.js +1 -1
  20. package/build/utils/emitter.js.map +1 -1
  21. package/build-module/components/use-dispatch/use-dispatch.js +8 -8
  22. package/build-module/components/use-dispatch/use-dispatch.js.map +1 -1
  23. package/build-module/components/use-select/index.js +60 -44
  24. package/build-module/components/use-select/index.js.map +1 -1
  25. package/build-module/controls.js +16 -16
  26. package/build-module/controls.js.map +1 -1
  27. package/build-module/index.js +14 -14
  28. package/build-module/index.js.map +1 -1
  29. package/build-module/redux-store/index.js +15 -15
  30. package/build-module/redux-store/index.js.map +1 -1
  31. package/build-module/registry.js +78 -68
  32. package/build-module/registry.js.map +1 -1
  33. package/build-module/resolvers-cache-middleware.js +3 -3
  34. package/build-module/resolvers-cache-middleware.js.map +1 -1
  35. package/build-module/store/index.js +42 -42
  36. package/build-module/store/index.js.map +1 -1
  37. package/build-module/utils/emitter.js +1 -1
  38. package/build-module/utils/emitter.js.map +1 -1
  39. package/build-types/types.d.ts +29 -16
  40. package/build-types/types.d.ts.map +1 -1
  41. package/build-types/utils/emitter.d.ts +2 -2
  42. package/build-types/utils/emitter.d.ts.map +1 -1
  43. package/package.json +9 -11
  44. package/src/components/use-dispatch/test/use-dispatch.js +1 -1
  45. package/src/components/use-dispatch/use-dispatch.js +9 -9
  46. package/src/components/use-select/index.js +61 -46
  47. package/src/components/use-select/test/index.js +32 -32
  48. package/src/controls.js +22 -22
  49. package/src/index.js +14 -14
  50. package/src/redux-store/index.js +15 -15
  51. package/src/registry.js +84 -75
  52. package/src/resolvers-cache-middleware.js +3 -3
  53. package/src/store/index.js +49 -48
  54. package/src/test/registry.js +32 -46
  55. package/src/types.ts +44 -16
  56. package/src/utils/emitter.js +1 -1
  57. package/tsconfig.tsbuildinfo +1 -1
  58. package/build/store/name.js +0 -15
  59. package/build/store/name.js.map +0 -1
  60. package/build-module/store/name.js +0 -7
  61. package/build-module/store/name.js.map +0 -1
  62. package/src/store/name.js +0 -6
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 6.1.5-next.0 (2021-12-20)
6
+
7
+ ### Bug Fix
8
+
9
+ - Corrected expect type of action creators and selectors in Redux store configuration type
10
+ - Move `redux` to regular dependencies and update it to version `^4.1.2`.
11
+
12
+ ### Internal
13
+
14
+ - Changed names of store-related types to better reflect their use and role.
15
+ - Changed "storeDefinition" to "storeDescriptor" to better reflect its use and role.
16
+
5
17
  ## 6.1.0 (2021-09-09)
6
18
 
7
19
  ### New Features
package/README.md CHANGED
@@ -16,7 +16,7 @@ _This package assumes that your code will run in an **ES2015+** environment. If
16
16
 
17
17
  ## Registering a Store
18
18
 
19
- Use the `register` function to add your own store to the centralized data registry. This function accepts one argument – a store definition object that can be created with `createReduxStore` factory function. `createReduxStore` accepts two arguments: a name to identify the module, and an object with values describing how your state is represented, modified, and accessed. At a minimum, you must provide a reducer function describing the shape of your state and how it changes in response to actions dispatched to the store.
19
+ Use the `register` function to add your own store to the centralized data registry. This function accepts one argument – a store descriptor that can be created with `createReduxStore` factory function. `createReduxStore` accepts two arguments: a name to identify the module, and a configuration object with values describing how your state is represented, modified, and accessed. At a minimum, you must provide a reducer function describing the shape of your state and how it changes in response to actions dispatched to the store.
20
20
 
21
21
  ```js
22
22
  import apiFetch from '@wordpress/api-fetch';
@@ -102,7 +102,7 @@ const store = createReduxStore( 'my-shop', {
102
102
  register( store );
103
103
  ```
104
104
 
105
- The return value of `createReduxStore` is the `WPDataStore` object that contains two properties:
105
+ The return value of `createReduxStore` is the `StoreDescriptor` object that contains two properties:
106
106
 
107
107
  - `name` (`string`) – the name of the store
108
108
  - `instantiate` (`Function`) - it returns a [Redux-like store object](https://redux.js.org/basics/store) with the following methods:
@@ -164,43 +164,33 @@ Integrating an existing redux store with its own reducers, store enhancers and m
164
164
  _Example:_
165
165
 
166
166
  ```js
167
+ import { mapValues } from 'lodash';
168
+ import { register } from '@wordpress/data';
167
169
  import existingSelectors from './existing-app/selectors';
168
170
  import existingActions from './existing-app/actions';
169
171
  import createStore from './existing-app/store';
170
172
 
171
- import { registerGenericStore } from 'wordpress/data';
172
-
173
173
  const reduxStore = createStore();
174
174
 
175
- const mappedSelectors = Object.keys( existingSelectors ).reduce(
176
- ( acc, selectorKey ) => {
177
- acc[ selectorKey ] = ( ...args ) =>
178
- existingSelectors[ selectorKey ]( reduxStore.getState(), ...args );
179
- return acc;
180
- },
181
- {}
175
+ const boundSelectors = mapValues(
176
+ existingSelectors,
177
+ ( selector ) => ( ...args ) => selector( reduxStore.getState(), ...args )
182
178
  );
183
179
 
184
- const mappedActions = Object.keys( existingActions ).reduce(
185
- ( acc, actionKey ) => {
186
- acc[ actionKey ] = ( ...args ) =>
187
- reduxStore.dispatch( existingActions[ actionKey ]( ...args ) );
188
- return acc;
189
- },
190
- {}
180
+ const boundActions = mapValues( existingActions, ( action ) => ( ...args ) =>
181
+ reduxStore.dispatch( action( ...args ) )
191
182
  );
192
183
 
193
184
  const genericStore = {
194
- getSelectors() {
195
- return mappedSelectors;
196
- },
197
- getActions() {
198
- return mappedActions;
199
- },
200
- subscribe: reduxStore.subscribe,
185
+ name: 'existing-app',
186
+ instantiate: () => ( {
187
+ getSelectors: () => boundSelectors,
188
+ getActions: () => boundActions,
189
+ subscribe: reduxStore.subscribe,
190
+ } ),
201
191
  };
202
192
 
203
- registerGenericStore( 'existing-app', genericStore );
193
+ register( genericStore );
204
194
  ```
205
195
 
206
196
  It is also possible to implement a completely custom store from scratch:
@@ -208,39 +198,49 @@ It is also possible to implement a completely custom store from scratch:
208
198
  _Example:_
209
199
 
210
200
  ```js
211
- import { registerGenericStore } from '@wordpress/data';
212
-
213
- function createCustomStore() {
214
- let storeChanged = () => {};
215
- const prices = { hammer: 7.5 };
216
-
217
- const selectors = {
218
- getPrice( itemName ) {
219
- return prices[ itemName ];
220
- },
221
- };
222
-
223
- const actions = {
224
- setPrice( itemName, price ) {
225
- prices[ itemName ] = price;
226
- storeChanged();
227
- },
228
- };
201
+ import { register } from '@wordpress/data';
229
202
 
203
+ function customStore() {
230
204
  return {
231
- getSelectors() {
232
- return selectors;
233
- },
234
- getActions() {
235
- return actions;
236
- },
237
- subscribe( listener ) {
238
- storeChanged = listener;
205
+ name: 'custom-data',
206
+ instantiate: () => {
207
+ const listeners = new Set();
208
+ const prices = { hammer: 7.5 };
209
+
210
+ function storeChanged() {
211
+ for ( const listener of listeners ) {
212
+ listener();
213
+ }
214
+ }
215
+
216
+ function subscribe( listener ) {
217
+ listeners.add( listener );
218
+ return () => listeners.delete( listener );
219
+ }
220
+
221
+ const selectors = {
222
+ getPrice( itemName ) {
223
+ return prices[ itemName ];
224
+ },
225
+ };
226
+
227
+ const actions = {
228
+ setPrice( itemName, price ) {
229
+ prices[ itemName ] = price;
230
+ storeChanged();
231
+ },
232
+ };
233
+
234
+ return {
235
+ getSelectors: () => selectors,
236
+ getActions: () => actions,
237
+ subscribe,
238
+ };
239
239
  },
240
240
  };
241
241
  }
242
242
 
243
- registerGenericStore( 'custom-data', createCustomStore() );
243
+ register( customStore );
244
244
  ```
245
245
 
246
246
  ## Comparison with Redux
@@ -350,7 +350,7 @@ Undocumented declaration.
350
350
 
351
351
  ### createReduxStore
352
352
 
353
- Creates a data store definition for the provided Redux store options containing
353
+ Creates a data store descriptor for the provided Redux store configuration containing
354
354
  properties describing reducer, actions, selectors, controls and resolvers.
355
355
 
356
356
  _Usage_
@@ -369,11 +369,11 @@ const store = createReduxStore( 'demo', {
369
369
  _Parameters_
370
370
 
371
371
  - _key_ `string`: Unique namespace identifier.
372
- - _options_ `WPDataReduxStoreConfig`: Registered store options, with properties describing reducer, actions, selectors, and resolvers.
372
+ - _options_ `ReduxStoreConfig`: Registered store options, with properties describing reducer, actions, selectors, and resolvers.
373
373
 
374
374
  _Returns_
375
375
 
376
- - `WPDataStore`: Store Object.
376
+ - `StoreDescriptor`: Store Object.
377
377
 
378
378
  ### createRegistry
379
379
 
@@ -486,7 +486,7 @@ dispatch( 'my-shop' ).setPrice( 'hammer', 9.75 );
486
486
 
487
487
  _Parameters_
488
488
 
489
- - _storeNameOrDefinition_ `string|WPDataStore`: Unique namespace identifier for the store or the store definition.
489
+ - _storeNameOrDescriptor_ `string|StoreDescriptor`: Unique namespace identifier for the store or the store descriptor.
490
490
 
491
491
  _Returns_
492
492
 
@@ -506,7 +506,7 @@ _Type_
506
506
 
507
507
  ### register
508
508
 
509
- Registers a standard `@wordpress/data` store definition.
509
+ Registers a standard `@wordpress/data` store descriptor.
510
510
 
511
511
  _Usage_
512
512
 
@@ -524,18 +524,18 @@ register( store );
524
524
 
525
525
  _Parameters_
526
526
 
527
- - _store_ `WPDataStore`: Store definition.
527
+ - _store_ `StoreDescriptor`: Store descriptor.
528
528
 
529
529
  ### registerGenericStore
530
530
 
531
- > **Deprecated** Use `register` instead.
531
+ > **Deprecated** Use `register( storeDescriptor )` instead.
532
532
 
533
- Registers a generic store.
533
+ Registers a generic store instance.
534
534
 
535
535
  _Parameters_
536
536
 
537
- - _key_ `string`: Store registry key.
538
- - _config_ `Object`: Configuration (getSelectors, getActions, subscribe).
537
+ - _name_ `string`: Store registry name.
538
+ - _store_ `Object`: Store instance (`{ getSelectors, getActions, subscribe }`).
539
539
 
540
540
  ### registerStore
541
541
 
@@ -610,7 +610,7 @@ resolveSelect( 'my-shop' ).getPrice( 'hammer' ).then( console.log );
610
610
 
611
611
  _Parameters_
612
612
 
613
- - _storeNameOrDefinition_ `string|WPDataStore`: Unique namespace identifier for the store or the store definition.
613
+ - _storeNameOrDescriptor_ `string|StoreDescriptor`: Unique namespace identifier for the store or the store descriptor.
614
614
 
615
615
  _Returns_
616
616
 
@@ -618,7 +618,7 @@ _Returns_
618
618
 
619
619
  ### select
620
620
 
621
- Given the name or definition of a registered store, returns an object of the store's selectors.
621
+ Given the name or descriptor of a registered store, returns an object of the store's selectors.
622
622
  The selector functions are been pre-bound to pass the current state automatically.
623
623
  As a consumer, you need only pass arguments of the selector, if applicable.
624
624
 
@@ -632,7 +632,7 @@ select( 'my-shop' ).getPrice( 'hammer' );
632
632
 
633
633
  _Parameters_
634
634
 
635
- - _storeNameOrDefinition_ `string|WPDataStore`: Unique namespace identifier for the store or the store definition.
635
+ - _storeNameOrDescriptor_ `string|StoreDescriptor`: Unique namespace identifier for the store or the store descriptor.
636
636
 
637
637
  _Returns_
638
638
 
@@ -717,7 +717,7 @@ const SaleButton = ( { children } ) => {
717
717
 
718
718
  _Parameters_
719
719
 
720
- - _storeNameOrDefinition_ `[string|WPDataStore]`: Optionally provide the name of the store or its definition from which to retrieve action creators. If not provided, the registry.dispatch function is returned instead.
720
+ - _storeNameOrDescriptor_ `[string|StoreDescriptor]`: Optionally provide the name of the store or its descriptor from which to retrieve action creators. If not provided, the registry.dispatch function is returned instead.
721
721
 
722
722
  _Returns_
723
723
 
@@ -820,7 +820,7 @@ function Paste( { children } ) {
820
820
 
821
821
  _Parameters_
822
822
 
823
- - _\_mapSelect_ `Function|WPDataStore|string`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument. When a store key is passed, all selectors for the store will be returned. This is only meant for usage of these selectors in event callbacks, not for data needed to create the element tree.
823
+ - _mapSelect_ `Function|StoreDescriptor|string`: Function called on every state change. The returned value is exposed to the component implementing this hook. The function receives the `registry.select` method on the first argument and the `registry` on the second argument. When a store key is passed, all selectors for the store will be returned. This is only meant for usage of these selectors in event callbacks, not for data needed to create the element tree.
824
824
  - _deps_ `Array`: If provided, this memoizes the mapSelect so the same `mapSelect` is invoked on every state change unless the dependencies change.
825
825
 
826
826
  _Returns_
@@ -13,7 +13,7 @@ var _useRegistry = _interopRequireDefault(require("../registry-provider/use-regi
13
13
  * Internal dependencies
14
14
  */
15
15
 
16
- /** @typedef {import('./types').WPDataStore} WPDataStore */
16
+ /** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */
17
17
 
18
18
  /**
19
19
  * A custom react hook returning the current registry dispatch actions creators.
@@ -21,11 +21,11 @@ var _useRegistry = _interopRequireDefault(require("../registry-provider/use-regi
21
21
  * Note: The component using this hook must be within the context of a
22
22
  * RegistryProvider.
23
23
  *
24
- * @param {string|WPDataStore} [storeNameOrDefinition] Optionally provide the name of the
25
- * store or its definition from which to
26
- * retrieve action creators. If not
27
- * provided, the registry.dispatch
28
- * function is returned instead.
24
+ * @param {string|StoreDescriptor} [storeNameOrDescriptor] Optionally provide the name of the
25
+ * store or its descriptor from which to
26
+ * retrieve action creators. If not
27
+ * provided, the registry.dispatch
28
+ * function is returned instead.
29
29
  *
30
30
  * @example
31
31
  * This illustrates a pattern where you may need to retrieve dynamic data from
@@ -59,11 +59,11 @@ var _useRegistry = _interopRequireDefault(require("../registry-provider/use-regi
59
59
  * ```
60
60
  * @return {Function} A custom react hook.
61
61
  */
62
- const useDispatch = storeNameOrDefinition => {
62
+ const useDispatch = storeNameOrDescriptor => {
63
63
  const {
64
64
  dispatch
65
65
  } = (0, _useRegistry.default)();
66
- return storeNameOrDefinition === void 0 ? dispatch : dispatch(storeNameOrDefinition);
66
+ return storeNameOrDescriptor === void 0 ? dispatch : dispatch(storeNameOrDescriptor);
67
67
  };
68
68
 
69
69
  var _default = useDispatch;
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/data/src/components/use-dispatch/use-dispatch.js"],"names":["useDispatch","storeNameOrDefinition","dispatch"],"mappings":";;;;;;;;;AAGA;;AAHA;AACA;AACA;;AAGA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMA,WAAW,GAAKC,qBAAF,IAA6B;AAChD,QAAM;AAAEC,IAAAA;AAAF,MAAe,2BAArB;AACA,SAAOD,qBAAqB,KAAK,KAAK,CAA/B,GACJC,QADI,GAEJA,QAAQ,CAAED,qBAAF,CAFX;AAGA,CALD;;eAOeD,W","sourcesContent":["/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\n\n/** @typedef {import('./types').WPDataStore} WPDataStore */\n\n/**\n * A custom react hook returning the current registry dispatch actions creators.\n *\n * Note: The component using this hook must be within the context of a\n * RegistryProvider.\n *\n * @param {string|WPDataStore} [storeNameOrDefinition] Optionally provide the name of the\n * store or its definition from which to\n * retrieve action creators. If not\n * provided, the registry.dispatch\n * function is returned instead.\n *\n * @example\n * This illustrates a pattern where you may need to retrieve dynamic data from\n * the server via the `useSelect` hook to use in combination with the dispatch\n * action.\n *\n * ```jsx\n * import { useDispatch, useSelect } from '@wordpress/data';\n * import { useCallback } from '@wordpress/element';\n *\n * function Button( { onClick, children } ) {\n * return <button type=\"button\" onClick={ onClick }>{ children }</button>\n * }\n *\n * const SaleButton = ( { children } ) => {\n * const { stockNumber } = useSelect(\n * ( select ) => select( 'my-shop' ).getStockNumber(),\n * []\n * );\n * const { startSale } = useDispatch( 'my-shop' );\n * const onClick = useCallback( () => {\n * const discountPercent = stockNumber > 50 ? 10: 20;\n * startSale( discountPercent );\n * }, [ stockNumber ] );\n * return <Button onClick={ onClick }>{ children }</Button>\n * }\n *\n * // Rendered somewhere in the application:\n * //\n * // <SaleButton>Start Sale!</SaleButton>\n * ```\n * @return {Function} A custom react hook.\n */\nconst useDispatch = ( storeNameOrDefinition ) => {\n\tconst { dispatch } = useRegistry();\n\treturn storeNameOrDefinition === void 0\n\t\t? dispatch\n\t\t: dispatch( storeNameOrDefinition );\n};\n\nexport default useDispatch;\n"]}
1
+ {"version":3,"sources":["@wordpress/data/src/components/use-dispatch/use-dispatch.js"],"names":["useDispatch","storeNameOrDescriptor","dispatch"],"mappings":";;;;;;;;;AAGA;;AAHA;AACA;AACA;;AAGA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMA,WAAW,GAAKC,qBAAF,IAA6B;AAChD,QAAM;AAAEC,IAAAA;AAAF,MAAe,2BAArB;AACA,SAAOD,qBAAqB,KAAK,KAAK,CAA/B,GACJC,QADI,GAEJA,QAAQ,CAAED,qBAAF,CAFX;AAGA,CALD;;eAOeD,W","sourcesContent":["/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\n\n/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */\n\n/**\n * A custom react hook returning the current registry dispatch actions creators.\n *\n * Note: The component using this hook must be within the context of a\n * RegistryProvider.\n *\n * @param {string|StoreDescriptor} [storeNameOrDescriptor] Optionally provide the name of the\n * store or its descriptor from which to\n * retrieve action creators. If not\n * provided, the registry.dispatch\n * function is returned instead.\n *\n * @example\n * This illustrates a pattern where you may need to retrieve dynamic data from\n * the server via the `useSelect` hook to use in combination with the dispatch\n * action.\n *\n * ```jsx\n * import { useDispatch, useSelect } from '@wordpress/data';\n * import { useCallback } from '@wordpress/element';\n *\n * function Button( { onClick, children } ) {\n * return <button type=\"button\" onClick={ onClick }>{ children }</button>\n * }\n *\n * const SaleButton = ( { children } ) => {\n * const { stockNumber } = useSelect(\n * ( select ) => select( 'my-shop' ).getStockNumber(),\n * []\n * );\n * const { startSale } = useDispatch( 'my-shop' );\n * const onClick = useCallback( () => {\n * const discountPercent = stockNumber > 50 ? 10: 20;\n * startSale( discountPercent );\n * }, [ stockNumber ] );\n * return <Button onClick={ onClick }>{ children }</Button>\n * }\n *\n * // Rendered somewhere in the application:\n * //\n * // <SaleButton>Start Sale!</SaleButton>\n * ```\n * @return {Function} A custom react hook.\n */\nconst useDispatch = ( storeNameOrDescriptor ) => {\n\tconst { dispatch } = useRegistry();\n\treturn storeNameOrDescriptor === void 0\n\t\t? dispatch\n\t\t: dispatch( storeNameOrDescriptor );\n};\n\nexport default useDispatch;\n"]}
@@ -32,8 +32,10 @@ var _useAsyncMode = _interopRequireDefault(require("../async-mode-provider/use-a
32
32
  /**
33
33
  * Internal dependencies
34
34
  */
35
+ const noop = () => {};
36
+
35
37
  const renderQueue = (0, _priorityQueue.createQueue)();
36
- /** @typedef {import('./types').WPDataStore} WPDataStore */
38
+ /** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */
37
39
 
38
40
  /**
39
41
  * Custom react hook for retrieving props from registered selectors.
@@ -41,20 +43,20 @@ const renderQueue = (0, _priorityQueue.createQueue)();
41
43
  * In general, this custom React hook follows the
42
44
  * [rules of hooks](https://reactjs.org/docs/hooks-rules.html).
43
45
  *
44
- * @param {Function|WPDataStore|string} _mapSelect Function called on every state change. The
45
- * returned value is exposed to the component
46
- * implementing this hook. The function receives
47
- * the `registry.select` method on the first
48
- * argument and the `registry` on the second
49
- * argument.
50
- * When a store key is passed, all selectors for
51
- * the store will be returned. This is only meant
52
- * for usage of these selectors in event
53
- * callbacks, not for data needed to create the
54
- * element tree.
55
- * @param {Array} deps If provided, this memoizes the mapSelect so the
56
- * same `mapSelect` is invoked on every state
57
- * change unless the dependencies change.
46
+ * @param {Function|StoreDescriptor|string} mapSelect Function called on every state change. The
47
+ * returned value is exposed to the component
48
+ * implementing this hook. The function receives
49
+ * the `registry.select` method on the first
50
+ * argument and the `registry` on the second
51
+ * argument.
52
+ * When a store key is passed, all selectors for
53
+ * the store will be returned. This is only meant
54
+ * for usage of these selectors in event
55
+ * callbacks, not for data needed to create the
56
+ * element tree.
57
+ * @param {Array} deps If provided, this memoizes the mapSelect so the
58
+ * same `mapSelect` is invoked on every state
59
+ * change unless the dependencies change.
58
60
  *
59
61
  * @example
60
62
  * ```js
@@ -103,14 +105,24 @@ const renderQueue = (0, _priorityQueue.createQueue)();
103
105
  * @return {Function} A custom react hook.
104
106
  */
105
107
 
106
- function useSelect(_mapSelect, deps) {
107
- const isWithoutMapping = typeof _mapSelect !== 'function';
108
+ function useSelect(mapSelect, deps) {
109
+ const hasMappingFunction = 'function' === typeof mapSelect; // If we're recalling a store by its name or by
110
+ // its descriptor then we won't be caching the
111
+ // calls to `mapSelect` because we won't be calling it.
108
112
 
109
- if (isWithoutMapping) {
113
+ if (!hasMappingFunction) {
110
114
  deps = [];
111
- }
115
+ } // Because of the "rule of hooks" we have to call `useCallback`
116
+ // on every invocation whether or not we have a real function
117
+ // for `mapSelect`. we'll create this intermediate variable to
118
+ // fulfill that need and then reference it with our "real"
119
+ // `_mapSelect` if we can.
120
+
121
+
122
+ const callbackMapper = (0, _element.useCallback)(hasMappingFunction ? mapSelect : noop, deps);
123
+
124
+ const _mapSelect = hasMappingFunction ? callbackMapper : null;
112
125
 
113
- const mapSelect = (0, _element.useCallback)(_mapSelect, deps);
114
126
  const registry = (0, _useRegistry.default)();
115
127
  const isAsync = (0, _useAsyncMode.default)(); // React can sometimes clear the `useMemo` cache.
116
128
  // We use the cache-stable `useMemoOne` to avoid
@@ -124,7 +136,7 @@ function useSelect(_mapSelect, deps) {
124
136
  const latestIsAsync = (0, _element.useRef)(isAsync);
125
137
  const latestMapOutput = (0, _element.useRef)();
126
138
  const latestMapOutputError = (0, _element.useRef)();
127
- const isMountedAndNotUnsubscribing = (0, _element.useRef)(); // Keep track of the stores being selected in the mapSelect function,
139
+ const isMountedAndNotUnsubscribing = (0, _element.useRef)(); // Keep track of the stores being selected in the _mapSelect function,
128
140
  // and only subscribe to those stores later.
129
141
 
130
142
  const listeningStores = (0, _element.useRef)([]);
@@ -135,34 +147,35 @@ function useSelect(_mapSelect, deps) {
135
147
  const depsChangedFlag = (0, _element.useMemo)(() => ({}), deps || []);
136
148
  let mapOutput;
137
149
 
138
- if (!isWithoutMapping) {
139
- try {
140
- if (latestMapSelect.current !== mapSelect || latestMapOutputError.current) {
141
- mapOutput = trapSelect(() => mapSelect(registry.select, registry));
142
- } else {
143
- mapOutput = latestMapOutput.current;
144
- }
145
- } catch (error) {
146
- let errorMessage = `An error occurred while running 'mapSelect': ${error.message}`;
150
+ if (_mapSelect) {
151
+ mapOutput = latestMapOutput.current;
152
+ const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;
153
+ const lastMapSelectFailed = !!latestMapOutputError.current;
154
+
155
+ if (hasReplacedMapSelect || lastMapSelectFailed) {
156
+ try {
157
+ mapOutput = trapSelect(() => _mapSelect(registry.select, registry));
158
+ } catch (error) {
159
+ let errorMessage = `An error occurred while running 'mapSelect': ${error.message}`;
147
160
 
148
- if (latestMapOutputError.current) {
149
- errorMessage += `\nThe error may be correlated with this previous error:\n`;
150
- errorMessage += `${latestMapOutputError.current.stack}\n\n`;
151
- errorMessage += 'Original stack trace:';
152
- } // eslint-disable-next-line no-console
161
+ if (latestMapOutputError.current) {
162
+ errorMessage += `\nThe error may be correlated with this previous error:\n`;
163
+ errorMessage += `${latestMapOutputError.current.stack}\n\n`;
164
+ errorMessage += 'Original stack trace:';
165
+ } // eslint-disable-next-line no-console
153
166
 
154
167
 
155
- console.error(errorMessage);
156
- mapOutput = latestMapOutput.current;
168
+ console.error(errorMessage);
169
+ }
157
170
  }
158
171
  }
159
172
 
160
173
  (0, _compose.useIsomorphicLayoutEffect)(() => {
161
- if (isWithoutMapping) {
174
+ if (!hasMappingFunction) {
162
175
  return;
163
176
  }
164
177
 
165
- latestMapSelect.current = mapSelect;
178
+ latestMapSelect.current = _mapSelect;
166
179
  latestMapOutput.current = mapOutput;
167
180
  latestMapOutputError.current = undefined;
168
181
  isMountedAndNotUnsubscribing.current = true; // This has to run after the other ref updates
@@ -176,7 +189,7 @@ function useSelect(_mapSelect, deps) {
176
189
  }
177
190
  });
178
191
  (0, _compose.useIsomorphicLayoutEffect)(() => {
179
- if (isWithoutMapping) {
192
+ if (!hasMappingFunction) {
180
193
  return;
181
194
  }
182
195
 
@@ -220,8 +233,10 @@ function useSelect(_mapSelect, deps) {
220
233
 
221
234
  unsubscribers.forEach(unsubscribe => unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe());
222
235
  renderQueue.flush(queueContext);
223
- };
224
- }, [registry, trapSelect, depsChangedFlag, isWithoutMapping]);
225
- return isWithoutMapping ? registry.select(_mapSelect) : mapOutput;
236
+ }; // If you're tempted to eliminate the spread dependencies below don't do it!
237
+ // We're passing these in from the calling function and want to make sure we're
238
+ // examining every individual value inside the `deps` array.
239
+ }, [registry, trapSelect, hasMappingFunction, depsChangedFlag]);
240
+ return hasMappingFunction ? mapOutput : registry.select(mapSelect);
226
241
  }
227
242
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["renderQueue","useSelect","_mapSelect","deps","isWithoutMapping","mapSelect","registry","isAsync","queueContext","queue","forceRender","s","latestMapSelect","latestIsAsync","latestMapOutput","latestMapOutputError","isMountedAndNotUnsubscribing","listeningStores","trapSelect","callback","__experimentalMarkListeningStores","depsChangedFlag","mapOutput","current","select","error","errorMessage","message","stack","console","undefined","flush","onStoreChange","newMapOutput","add","onChange","unsubscribers","map","storeName","__experimentalSubscribeStore","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, useReducer, useMemo } 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 renderQueue = createQueue();\n\n/** @typedef {import('./types').WPDataStore} WPDataStore */\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|WPDataStore|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 isWithoutMapping = typeof _mapSelect !== 'function';\n\n\tif ( isWithoutMapping ) {\n\t\tdeps = [];\n\t}\n\n\tconst mapSelect = useCallback( _mapSelect, deps );\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 trapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__experimentalMarkListeningStores(\n\t\t\t\tcallback,\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 ( ! isWithoutMapping ) {\n\t\ttry {\n\t\t\tif (\n\t\t\t\tlatestMapSelect.current !== mapSelect ||\n\t\t\t\tlatestMapOutputError.current\n\t\t\t) {\n\t\t\t\tmapOutput = trapSelect( () =>\n\t\t\t\t\tmapSelect( registry.select, registry )\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tmapOutput = latestMapOutput.current;\n\t\t\t}\n\t\t} catch ( error ) {\n\t\t\tlet errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;\n\n\t\t\tif ( latestMapOutputError.current ) {\n\t\t\t\terrorMessage += `\\nThe error may be correlated with this previous error:\\n`;\n\t\t\t\terrorMessage += `${ latestMapOutputError.current.stack }\\n\\n`;\n\t\t\t\terrorMessage += 'Original stack trace:';\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.error( errorMessage );\n\t\t\tmapOutput = latestMapOutput.current;\n\t\t}\n\t}\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( isWithoutMapping ) {\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 ( isWithoutMapping ) {\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 = trapSelect( () =>\n\t\t\t\t\t\tlatestMapSelect.current( registry.select, registry )\n\t\t\t\t\t);\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\t// catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tif ( latestIsAsync.current ) {\n\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t} else {\n\t\t\tonStoreChange();\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\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.__experimentalSubscribeStore( 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}, [ registry, trapSelect, depsChangedFlag, isWithoutMapping ] );\n\n\treturn isWithoutMapping ? registry.select( _mapSelect ) : mapOutput;\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","latestMapSelect","latestIsAsync","latestMapOutput","latestMapOutputError","isMountedAndNotUnsubscribing","listeningStores","trapSelect","callback","__experimentalMarkListeningStores","depsChangedFlag","mapOutput","current","hasReplacedMapSelect","lastMapSelectFailed","select","error","errorMessage","message","stack","console","undefined","flush","onStoreChange","newMapOutput","add","onChange","unsubscribers","map","storeName","__experimentalSubscribeStore","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 trapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__experimentalMarkListeningStores(\n\t\t\t\tcallback,\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 = trapSelect( () =>\n\t\t\t\t\t_mapSelect( registry.select, registry )\n\t\t\t\t);\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 = trapSelect( () =>\n\t\t\t\t\t\tlatestMapSelect.current( registry.select, registry )\n\t\t\t\t\t);\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\t// catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tif ( latestIsAsync.current ) {\n\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t} else {\n\t\t\tonStoreChange();\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\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.__experimentalSubscribeStore( 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, trapSelect, hasMappingFunction, depsChangedFlag ] );\n\n\treturn hasMappingFunction ? mapOutput : registry.select( mapSelect );\n}\n"]}