@wordpress/data 8.6.0 → 9.1.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 CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 9.1.0 (2023-04-12)
6
+
7
+ ## 9.0.0 (2023-03-29)
8
+
9
+ ### Breaking Changes
10
+
11
+ - The `registry.register` function will no longer register a store if another instance is registered with the same name.
12
+
5
13
  ## 8.6.0 (2023-03-15)
6
14
 
7
15
  ## 8.5.0 (2023-03-01)
package/README.md CHANGED
@@ -279,8 +279,7 @@ Specific implementation differences from Redux and React Redux:
279
279
 
280
280
  ### AsyncModeProvider
281
281
 
282
- Context Provider Component used to switch the data module component rerendering
283
- between Sync and Async modes.
282
+ Context Provider Component used to switch the data module component rerendering between Sync and Async modes.
284
283
 
285
284
  _Usage_
286
285
 
@@ -320,8 +319,7 @@ _Returns_
320
319
 
321
320
  ### combineReducers
322
321
 
323
- The combineReducers helper function turns an object whose values are different
324
- reducing functions into a single reducing function you can pass to registerReducer.
322
+ The combineReducers helper function turns an object whose values are different reducing functions into a single reducing function you can pass to registerReducer.
325
323
 
326
324
  _Usage_
327
325
 
@@ -368,8 +366,7 @@ Undocumented declaration.
368
366
 
369
367
  ### createReduxStore
370
368
 
371
- Creates a data store descriptor for the provided Redux store configuration containing
372
- properties describing reducer, actions, selectors, controls and resolvers.
369
+ Creates a data store descriptor for the provided Redux store configuration containing properties describing reducer, actions, selectors, controls and resolvers.
373
370
 
374
371
  _Usage_
375
372
 
@@ -395,8 +392,7 @@ _Returns_
395
392
 
396
393
  ### createRegistry
397
394
 
398
- Creates a new store registry, given an optional object of initial store
399
- configurations.
395
+ Creates a new store registry, given an optional object of initial store configurations.
400
396
 
401
397
  _Parameters_
402
398
 
@@ -409,8 +405,7 @@ _Returns_
409
405
 
410
406
  ### createRegistryControl
411
407
 
412
- Creates a control function that takes additional curried argument with the `registry` object.
413
- While a regular control has signature
408
+ Creates a control function that takes additional curried argument with the `registry` object. While a regular control has signature
414
409
 
415
410
  ```js
416
411
  ( action ) => iteratorOrPromise;
@@ -422,11 +417,9 @@ where the control works with the `action` that it's bound to, a registry control
422
417
  ( registry ) => ( action ) => iteratorOrPromise;
423
418
  ```
424
419
 
425
- A registry control is typically used to select data or dispatch an action to a registered
426
- store.
420
+ A registry control is typically used to select data or dispatch an action to a registered store.
427
421
 
428
- When registering a control created with `createRegistryControl` with a store, the store
429
- knows which calling convention to use when executing the control.
422
+ When registering a control created with `createRegistryControl` with a store, the store knows which calling convention to use when executing the control.
430
423
 
431
424
  _Parameters_
432
425
 
@@ -438,15 +431,13 @@ _Returns_
438
431
 
439
432
  ### createRegistrySelector
440
433
 
441
- Creates a selector function that takes additional curried argument with the
442
- registry `select` function. While a regular selector has signature
434
+ Creates a selector function that takes additional curried argument with the registry `select` function. While a regular selector has signature
443
435
 
444
436
  ```js
445
437
  ( state, ...selectorArgs ) => result;
446
438
  ```
447
439
 
448
- that allows to select data from the store's `state`, a registry selector
449
- has signature:
440
+ that allows to select data from the store's `state`, a registry selector has signature:
450
441
 
451
442
  ```js
452
443
  ( select ) =>
@@ -493,11 +484,9 @@ _Returns_
493
484
 
494
485
  ### dispatch
495
486
 
496
- Given a store descriptor, returns an object of the store's action creators.
497
- Calling an action creator will cause it to be dispatched, updating the state value accordingly.
487
+ Given a store descriptor, returns an object of the store's action creators. Calling an action creator will cause it to be dispatched, updating the state value accordingly.
498
488
 
499
- Note: Action creators returned by the dispatch will return a promise when
500
- they are called.
489
+ Note: Action creators returned by the dispatch will return a promise when they are called.
501
490
 
502
491
  _Usage_
503
492
 
@@ -578,11 +567,9 @@ _Returns_
578
567
 
579
568
  ### RegistryConsumer
580
569
 
581
- A custom react Context consumer exposing the provided `registry` to
582
- children components. Used along with the RegistryProvider.
570
+ A custom react Context consumer exposing the provided `registry` to children components. Used along with the RegistryProvider.
583
571
 
584
- You can read more about the react context api here:
585
- <https://reactjs.org/docs/context.html#contextprovider>
572
+ You can read more about the react context api here: <https://reactjs.org/docs/context.html#contextprovider>
586
573
 
587
574
  _Usage_
588
575
 
@@ -611,17 +598,13 @@ const App = ( { props } ) => {
611
598
 
612
599
  ### RegistryProvider
613
600
 
614
- A custom Context provider for exposing the provided `registry` to children
615
- components via a consumer.
601
+ A custom Context provider for exposing the provided `registry` to children components via a consumer.
616
602
 
617
- See <a name="#RegistryConsumer">RegistryConsumer</a> documentation for
618
- example.
603
+ See <a name="#RegistryConsumer">RegistryConsumer</a> documentation for example.
619
604
 
620
605
  ### resolveSelect
621
606
 
622
- Given a store descriptor, returns an object containing the store's selectors pre-bound to state
623
- so that you only need to supply additional arguments, and modified so that they return promises
624
- that resolve to their eventual values, after any resolvers have ran.
607
+ Given a store descriptor, returns an object containing the store's selectors pre-bound to state so that you only need to supply additional arguments, and modified so that they return promises that resolve to their eventual values, after any resolvers have ran.
625
608
 
626
609
  _Usage_
627
610
 
@@ -642,9 +625,7 @@ _Returns_
642
625
 
643
626
  ### select
644
627
 
645
- Given a store descriptor, returns an object of the store's selectors.
646
- The selector functions are been pre-bound to pass the current state automatically.
647
- As a consumer, you need only pass arguments of the selector, if applicable.
628
+ Given a store descriptor, returns an object of the store's selectors. The selector functions are been pre-bound to pass the current state automatically. As a consumer, you need only pass arguments of the selector, if applicable.
648
629
 
649
630
  _Usage_
650
631
 
@@ -665,10 +646,7 @@ _Returns_
665
646
 
666
647
  ### subscribe
667
648
 
668
- Given a listener function, the function will be called any time the state value
669
- of one of the registered stores has changed. If you specify the optional
670
- `storeNameOrDescriptor` parameter, the listener function will be called only
671
- on updates on that one specific registered store.
649
+ Given a listener function, the function will be called any time the state value of one of the registered stores has changed. If you specify the optional `storeNameOrDescriptor` parameter, the listener function will be called only on updates on that one specific registered store.
672
650
 
673
651
  This function returns an `unsubscribe` function used to stop the subscription.
674
652
 
@@ -693,9 +671,7 @@ _Parameters_
693
671
 
694
672
  ### suspendSelect
695
673
 
696
- Given a store descriptor, returns an object containing the store's selectors pre-bound to state
697
- so that you only need to supply additional arguments, and modified so that they throw promises
698
- in case the selector is not resolved yet.
674
+ Given a store descriptor, returns an object containing the store's selectors pre-bound to state so that you only need to supply additional arguments, and modified so that they throw promises in case the selector is not resolved yet.
699
675
 
700
676
  _Parameters_
701
677
 
@@ -707,9 +683,7 @@ _Returns_
707
683
 
708
684
  ### use
709
685
 
710
- Extends a registry to inherit functionality provided by a given plugin. A
711
- plugin is an object with properties aligning to that of a registry, merged
712
- to extend the default registry behavior.
686
+ Extends a registry to inherit functionality provided by a given plugin. A plugin is an object with properties aligning to that of a registry, merged to extend the default registry behavior.
713
687
 
714
688
  _Parameters_
715
689
 
@@ -719,8 +693,7 @@ _Parameters_
719
693
 
720
694
  A custom react hook returning the current registry dispatch actions creators.
721
695
 
722
- Note: The component using this hook must be within the context of a
723
- RegistryProvider.
696
+ Note: The component using this hook must be within the context of a RegistryProvider.
724
697
 
725
698
  _Usage_
726
699
 
@@ -771,16 +744,11 @@ _Returns_
771
744
 
772
745
  A custom react hook exposing the registry context for use.
773
746
 
774
- This exposes the `registry` value provided via the
775
- <a href="#RegistryProvider">Registry Provider</a> to a component implementing
776
- this hook.
747
+ This exposes the `registry` value provided via the <a href="#RegistryProvider">Registry Provider</a> to a component implementing this hook.
777
748
 
778
749
  It acts similarly to the `useContext` react hook.
779
750
 
780
- Note: Generally speaking, `useRegistry` is a low level hook that in most cases
781
- won't be needed for implementation. Most interactions with the `@wordpress/data`
782
- API can be performed via the `useSelect` hook, or the `withSelect` and
783
- `withDispatch` higher order components.
751
+ Note: Generally speaking, `useRegistry` is a low level hook that in most cases won't be needed for implementation. Most interactions with the `@wordpress/data` API can be performed via the `useSelect` hook, or the `withSelect` and `withDispatch` higher order components.
784
752
 
785
753
  _Usage_
786
754
 
@@ -811,8 +779,7 @@ _Returns_
811
779
 
812
780
  Custom react hook for retrieving props from registered selectors.
813
781
 
814
- In general, this custom React hook follows the
815
- [rules of hooks](https://reactjs.org/docs/hooks-rules.html).
782
+ In general, this custom React hook follows the [rules of hooks](https://reactjs.org/docs/hooks-rules.html).
816
783
 
817
784
  _Usage_
818
785
 
@@ -875,8 +842,7 @@ _Returns_
875
842
 
876
843
  ### useSuspenseSelect
877
844
 
878
- A variant of the `useSelect` hook that has the same API, but will throw a
879
- suspense Promise if any of the called selectors is in an unresolved state.
845
+ A variant of the `useSelect` hook that has the same API, but will throw a suspense Promise if any of the called selectors is in an unresolved state.
880
846
 
881
847
  _Parameters_
882
848
 
@@ -889,8 +855,7 @@ _Returns_
889
855
 
890
856
  ### withDispatch
891
857
 
892
- Higher-order component used to add dispatch props using registered action
893
- creators.
858
+ Higher-order component used to add dispatch props using registered action creators.
894
859
 
895
860
  _Usage_
896
861
 
@@ -978,8 +943,7 @@ _Returns_
978
943
 
979
944
  ### withRegistry
980
945
 
981
- Higher-order component which renders the original component with the current
982
- registry context passed as its `registry` prop.
946
+ Higher-order component which renders the original component with the current registry context passed as its `registry` prop.
983
947
 
984
948
  _Parameters_
985
949
 
@@ -991,8 +955,7 @@ _Returns_
991
955
 
992
956
  ### withSelect
993
957
 
994
- Higher-order component used to inject state-derived props using registered
995
- selectors.
958
+ Higher-order component used to inject state-derived props using registered selectors.
996
959
 
997
960
  _Usage_
998
961
 
@@ -52,48 +52,87 @@ function Store(registry, suspense) {
52
52
  let lastMapResult;
53
53
  let lastMapResultValid = false;
54
54
  let lastIsAsync;
55
- let subscribe;
56
-
57
- const createSubscriber = stores => listener => {
58
- // Invalidate the value right after subscription was created. React will
59
- // call `getValue` after subscribing, to detect store updates that happened
60
- // in the interval between the `getValue` call during render and creating
61
- // the subscription, which is slightly delayed. We need to ensure that this
62
- // second `getValue` call will compute a fresh value.
63
- lastMapResultValid = false;
64
-
65
- const onStoreChange = () => {
66
- // Invalidate the value on store update, so that a fresh value is computed.
55
+ let subscriber;
56
+
57
+ const createSubscriber = stores => {
58
+ // The set of stores the `subscribe` function is supposed to subscribe to. Here it is
59
+ // initialized, and then the `updateStores` function can add new stores to it.
60
+ const activeStores = [...stores]; // The `subscribe` function, which is passed to the `useSyncExternalStore` hook, could
61
+ // be called multiple times to establish multiple subscriptions. That's why we need to
62
+ // keep a set of active subscriptions;
63
+
64
+ const activeSubscriptions = new Set();
65
+
66
+ function subscribe(listener) {
67
+ // Invalidate the value right after subscription was created. React will
68
+ // call `getValue` after subscribing, to detect store updates that happened
69
+ // in the interval between the `getValue` call during render and creating
70
+ // the subscription, which is slightly delayed. We need to ensure that this
71
+ // second `getValue` call will compute a fresh value.
67
72
  lastMapResultValid = false;
68
- listener();
69
- };
70
73
 
71
- const onChange = () => {
72
- if (lastIsAsync) {
73
- renderQueue.add(queueContext, onStoreChange);
74
- } else {
75
- onStoreChange();
74
+ const onStoreChange = () => {
75
+ // Invalidate the value on store update, so that a fresh value is computed.
76
+ lastMapResultValid = false;
77
+ listener();
78
+ };
79
+
80
+ const onChange = () => {
81
+ if (lastIsAsync) {
82
+ renderQueue.add(queueContext, onStoreChange);
83
+ } else {
84
+ onStoreChange();
85
+ }
86
+ };
87
+
88
+ const unsubs = [];
89
+
90
+ function subscribeStore(storeName) {
91
+ unsubs.push(registry.subscribe(onChange, storeName));
76
92
  }
77
- };
78
93
 
79
- const unsubs = stores.map(storeName => {
80
- return registry.subscribe(onChange, storeName);
81
- });
82
- return () => {
83
- // The return value of the subscribe function could be undefined if the store is a custom generic store.
84
- for (const unsub of unsubs) {
85
- unsub === null || unsub === void 0 ? void 0 : unsub();
86
- } // Cancel existing store updates that were already scheduled.
94
+ for (const storeName of activeStores) {
95
+ subscribeStore(storeName);
96
+ }
87
97
 
98
+ activeSubscriptions.add(subscribeStore);
99
+ return () => {
100
+ activeSubscriptions.delete(subscribeStore);
88
101
 
89
- renderQueue.cancel(queueContext);
102
+ for (const unsub of unsubs.values()) {
103
+ // The return value of the subscribe function could be undefined if the store is a custom generic store.
104
+ unsub === null || unsub === void 0 ? void 0 : unsub();
105
+ } // Cancel existing store updates that were already scheduled.
106
+
107
+
108
+ renderQueue.cancel(queueContext);
109
+ };
110
+ } // Check if `newStores` contains some stores we're not subscribed to yet, and add them.
111
+
112
+
113
+ function updateStores(newStores) {
114
+ for (const newStore of newStores) {
115
+ if (activeStores.includes(newStore)) {
116
+ continue;
117
+ } // New `subscribe` calls will subscribe to `newStore`, too.
118
+
119
+
120
+ activeStores.push(newStore); // Add `newStore` to existing subscriptions.
121
+
122
+ for (const subscription of activeSubscriptions) {
123
+ subscription(newStore);
124
+ }
125
+ }
126
+ }
127
+
128
+ return {
129
+ subscribe,
130
+ updateStores
90
131
  };
91
132
  };
92
133
 
93
- return (mapSelect, resubscribe, isAsync) => {
94
- const selectValue = () => mapSelect(select, registry);
95
-
96
- function updateValue(selectFromStore) {
134
+ return (mapSelect, isAsync) => {
135
+ function updateValue() {
97
136
  // If the last value is valid, and the `mapSelect` callback hasn't changed,
98
137
  // then we can safely return the cached value. The value can change only on
99
138
  // store update, and in that case value will be invalidated by the listener.
@@ -101,19 +140,31 @@ function Store(registry, suspense) {
101
140
  return lastMapResult;
102
141
  }
103
142
 
104
- const mapResult = selectFromStore(); // If the new value is shallow-equal to the old one, keep the old one so
143
+ const listeningStores = {
144
+ current: null
145
+ };
146
+
147
+ const mapResult = registry.__unstableMarkListeningStores(() => mapSelect(select, registry), listeningStores);
148
+
149
+ if (!subscriber) {
150
+ subscriber = createSubscriber(listeningStores.current);
151
+ } else {
152
+ subscriber.updateStores(listeningStores.current);
153
+ } // If the new value is shallow-equal to the old one, keep the old one so
105
154
  // that we don't trigger unwanted updates that do a `===` check.
106
155
 
156
+
107
157
  if (!(0, _isShallowEqual.default)(lastMapResult, mapResult)) {
108
158
  lastMapResult = mapResult;
109
159
  }
110
160
 
161
+ lastMapSelect = mapSelect;
111
162
  lastMapResultValid = true;
112
163
  }
113
164
 
114
165
  function getValue() {
115
166
  // Update the value in case it's been invalidated or `mapSelect` has changed.
116
- updateValue(selectValue);
167
+ updateValue();
117
168
  return lastMapResult;
118
169
  } // When transitioning from async to sync mode, cancel existing store updates
119
170
  // that have been scheduled, and invalidate the value so that it's freshly
@@ -123,29 +174,13 @@ function Store(registry, suspense) {
123
174
  if (lastIsAsync && !isAsync) {
124
175
  lastMapResultValid = false;
125
176
  renderQueue.cancel(queueContext);
126
- } // Either initialize the `subscribe` function, or create a new one if `mapSelect`
127
- // changed and has dependencies.
128
- // Usage without dependencies, `useSelect( ( s ) => { ... } )`, will subscribe
129
- // only once, at mount, and won't resubscibe even if `mapSelect` changes.
130
-
131
-
132
- if (!subscribe || resubscribe && mapSelect !== lastMapSelect) {
133
- // Find out what stores the `mapSelect` callback is selecting from and
134
- // use that list to create subscriptions to specific stores.
135
- const listeningStores = {
136
- current: null
137
- };
138
- updateValue(() => registry.__unstableMarkListeningStores(selectValue, listeningStores));
139
- subscribe = createSubscriber(listeningStores.current);
140
- } else {
141
- updateValue(selectValue);
142
177
  }
143
178
 
144
- lastIsAsync = isAsync;
145
- lastMapSelect = mapSelect; // Return a pair of functions that can be passed to `useSyncExternalStore`.
179
+ updateValue();
180
+ lastIsAsync = isAsync; // Return a pair of functions that can be passed to `useSyncExternalStore`.
146
181
 
147
182
  return {
148
- subscribe,
183
+ subscribe: subscriber.subscribe,
149
184
  getValue
150
185
  };
151
186
  };
@@ -163,7 +198,7 @@ function useMappingSelect(suspense, mapSelect, deps) {
163
198
  const {
164
199
  subscribe,
165
200
  getValue
166
- } = store(selector, !!deps, isAsync);
201
+ } = store(selector, isAsync);
167
202
  const result = (0, _element.useSyncExternalStore)(subscribe, getValue, getValue);
168
203
  (0, _element.useDebugValue)(result);
169
204
  return result;
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["renderQueue","Store","registry","suspense","select","suspendSelect","queueContext","lastMapSelect","lastMapResult","lastMapResultValid","lastIsAsync","subscribe","createSubscriber","stores","listener","onStoreChange","onChange","add","unsubs","map","storeName","unsub","cancel","mapSelect","resubscribe","isAsync","selectValue","updateValue","selectFromStore","mapResult","getValue","listeningStores","current","__unstableMarkListeningStores","useStaticSelect","useMappingSelect","deps","store","selector","result","useSelect","staticSelectMode","staticSelectModeRef","prevMode","nextMode","Error","useSuspenseSelect"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport {\n\tuseRef,\n\tuseCallback,\n\tuseMemo,\n\tuseSyncExternalStore,\n\tuseDebugValue,\n} from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\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/**\n * @typedef {import('../../types').StoreDescriptor<C>} StoreDescriptor\n * @template {import('../../types').AnyConfig} C\n */\n/**\n * @typedef {import('../../types').ReduxStoreConfig<State,Actions,Selectors>} ReduxStoreConfig\n * @template State\n * @template {Record<string,import('../../types').ActionCreator>} Actions\n * @template Selectors\n */\n/** @typedef {import('../../types').MapSelect} MapSelect */\n/**\n * @typedef {import('../../types').UseSelectReturn<T>} UseSelectReturn\n * @template {MapSelect|StoreDescriptor<any>} T\n */\n\nfunction Store( registry, suspense ) {\n\tconst select = suspense ? registry.suspendSelect : registry.select;\n\tconst queueContext = {};\n\tlet lastMapSelect;\n\tlet lastMapResult;\n\tlet lastMapResultValid = false;\n\tlet lastIsAsync;\n\tlet subscribe;\n\n\tconst createSubscriber = ( stores ) => ( listener ) => {\n\t\t// Invalidate the value right after subscription was created. React will\n\t\t// call `getValue` after subscribing, to detect store updates that happened\n\t\t// in the interval between the `getValue` call during render and creating\n\t\t// the subscription, which is slightly delayed. We need to ensure that this\n\t\t// second `getValue` call will compute a fresh value.\n\t\tlastMapResultValid = false;\n\n\t\tconst onStoreChange = () => {\n\t\t\t// Invalidate the value on store update, so that a fresh value is computed.\n\t\t\tlastMapResultValid = false;\n\t\t\tlistener();\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( lastIsAsync ) {\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 unsubs = stores.map( ( storeName ) => {\n\t\t\treturn registry.subscribe( onChange, storeName );\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\tfor ( const unsub of unsubs ) {\n\t\t\t\tunsub?.();\n\t\t\t}\n\t\t\t// Cancel existing store updates that were already scheduled.\n\t\t\trenderQueue.cancel( queueContext );\n\t\t};\n\t};\n\n\treturn ( mapSelect, resubscribe, isAsync ) => {\n\t\tconst selectValue = () => mapSelect( select, registry );\n\n\t\tfunction updateValue( selectFromStore ) {\n\t\t\t// If the last value is valid, and the `mapSelect` callback hasn't changed,\n\t\t\t// then we can safely return the cached value. The value can change only on\n\t\t\t// store update, and in that case value will be invalidated by the listener.\n\t\t\tif ( lastMapResultValid && mapSelect === lastMapSelect ) {\n\t\t\t\treturn lastMapResult;\n\t\t\t}\n\n\t\t\tconst mapResult = selectFromStore();\n\n\t\t\t// If the new value is shallow-equal to the old one, keep the old one so\n\t\t\t// that we don't trigger unwanted updates that do a `===` check.\n\t\t\tif ( ! isShallowEqual( lastMapResult, mapResult ) ) {\n\t\t\t\tlastMapResult = mapResult;\n\t\t\t}\n\t\t\tlastMapResultValid = true;\n\t\t}\n\n\t\tfunction getValue() {\n\t\t\t// Update the value in case it's been invalidated or `mapSelect` has changed.\n\t\t\tupdateValue( selectValue );\n\t\t\treturn lastMapResult;\n\t\t}\n\n\t\t// When transitioning from async to sync mode, cancel existing store updates\n\t\t// that have been scheduled, and invalidate the value so that it's freshly\n\t\t// computed. It might have been changed by the update we just cancelled.\n\t\tif ( lastIsAsync && ! isAsync ) {\n\t\t\tlastMapResultValid = false;\n\t\t\trenderQueue.cancel( queueContext );\n\t\t}\n\n\t\t// Either initialize the `subscribe` function, or create a new one if `mapSelect`\n\t\t// changed and has dependencies.\n\t\t// Usage without dependencies, `useSelect( ( s ) => { ... } )`, will subscribe\n\t\t// only once, at mount, and won't resubscibe even if `mapSelect` changes.\n\t\tif ( ! subscribe || ( resubscribe && mapSelect !== lastMapSelect ) ) {\n\t\t\t// Find out what stores the `mapSelect` callback is selecting from and\n\t\t\t// use that list to create subscriptions to specific stores.\n\t\t\tconst listeningStores = { current: null };\n\t\t\tupdateValue( () =>\n\t\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t\tselectValue,\n\t\t\t\t\tlisteningStores\n\t\t\t\t)\n\t\t\t);\n\t\t\tsubscribe = createSubscriber( listeningStores.current );\n\t\t} else {\n\t\t\tupdateValue( selectValue );\n\t\t}\n\n\t\tlastIsAsync = isAsync;\n\t\tlastMapSelect = mapSelect;\n\n\t\t// Return a pair of functions that can be passed to `useSyncExternalStore`.\n\t\treturn { subscribe, getValue };\n\t};\n}\n\nfunction useStaticSelect( storeName ) {\n\treturn useRegistry().select( storeName );\n}\n\nfunction useMappingSelect( suspense, mapSelect, deps ) {\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\tconst store = useMemo( () => Store( registry, suspense ), [ registry ] );\n\tconst selector = useCallback( mapSelect, deps );\n\tconst { subscribe, getValue } = store( selector, !! deps, isAsync );\n\tconst result = useSyncExternalStore( subscribe, getValue, getValue );\n\tuseDebugValue( result );\n\treturn result;\n}\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 * @template {MapSelect | StoreDescriptor<any>} T\n * @param {T} mapSelect Function called on every state change. The returned value is\n * exposed to the component implementing this hook. The function\n * receives the `registry.select` method on the first argument\n * and the `registry` on the second argument.\n * When a store key is passed, all selectors for the store will be\n * returned. This is only meant for usage of these selectors in event\n * callbacks, not for data needed to create the element tree.\n * @param {unknown[]} deps If provided, this memoizes the mapSelect so the same `mapSelect` is\n * invoked on every state change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n * import { store as myCustomStore } from 'my-custom-store';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( myCustomStore ).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 * import { store as myCustomStore } from 'my-custom-store';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( myCustomStore );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n * @return {UseSelectReturn<T>} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\t// On initial call, on mount, determine the mode of this `useSelect` call\n\t// and then never allow it to change on subsequent updates.\n\tconst staticSelectMode = typeof mapSelect !== 'function';\n\tconst staticSelectModeRef = useRef( staticSelectMode );\n\n\tif ( staticSelectMode !== staticSelectModeRef.current ) {\n\t\tconst prevMode = staticSelectModeRef.current ? 'static' : 'mapping';\n\t\tconst nextMode = staticSelectMode ? 'static' : 'mapping';\n\t\tthrow new Error(\n\t\t\t`Switching useSelect from ${ prevMode } to ${ nextMode } is not allowed`\n\t\t);\n\t}\n\n\t/* eslint-disable react-hooks/rules-of-hooks */\n\t// `staticSelectMode` is not allowed to change during the hook instance's,\n\t// lifetime, so the rules of hooks are not really violated.\n\treturn staticSelectMode\n\t\t? useStaticSelect( mapSelect )\n\t\t: useMappingSelect( false, mapSelect, deps );\n\t/* eslint-enable react-hooks/rules-of-hooks */\n}\n\n/**\n * A variant of the `useSelect` hook that has the same API, but will throw a\n * suspense Promise if any of the called selectors is in an unresolved state.\n *\n * @param {Function} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * using this hook. The function receives the\n * `registry.suspendSelect` method as the first\n * argument and the `registry` as the second one.\n * @param {Array} deps A dependency array used to memoize the `mapSelect`\n * so that the same `mapSelect` is invoked on every\n * state change unless the dependencies change.\n *\n * @return {Object} Data object returned by the `mapSelect` function.\n */\nexport function useSuspenseSelect( mapSelect, deps ) {\n\treturn useMappingSelect( true, mapSelect, deps );\n}\n"]}
1
+ {"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["renderQueue","Store","registry","suspense","select","suspendSelect","queueContext","lastMapSelect","lastMapResult","lastMapResultValid","lastIsAsync","subscriber","createSubscriber","stores","activeStores","activeSubscriptions","Set","subscribe","listener","onStoreChange","onChange","add","unsubs","subscribeStore","storeName","push","delete","unsub","values","cancel","updateStores","newStores","newStore","includes","subscription","mapSelect","isAsync","updateValue","listeningStores","current","mapResult","__unstableMarkListeningStores","getValue","useStaticSelect","useMappingSelect","deps","store","selector","result","useSelect","staticSelectMode","staticSelectModeRef","prevMode","nextMode","Error","useSuspenseSelect"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport {\n\tuseRef,\n\tuseCallback,\n\tuseMemo,\n\tuseSyncExternalStore,\n\tuseDebugValue,\n} from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\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/**\n * @typedef {import('../../types').StoreDescriptor<C>} StoreDescriptor\n * @template {import('../../types').AnyConfig} C\n */\n/**\n * @typedef {import('../../types').ReduxStoreConfig<State,Actions,Selectors>} ReduxStoreConfig\n * @template State\n * @template {Record<string,import('../../types').ActionCreator>} Actions\n * @template Selectors\n */\n/** @typedef {import('../../types').MapSelect} MapSelect */\n/**\n * @typedef {import('../../types').UseSelectReturn<T>} UseSelectReturn\n * @template {MapSelect|StoreDescriptor<any>} T\n */\n\nfunction Store( registry, suspense ) {\n\tconst select = suspense ? registry.suspendSelect : registry.select;\n\tconst queueContext = {};\n\tlet lastMapSelect;\n\tlet lastMapResult;\n\tlet lastMapResultValid = false;\n\tlet lastIsAsync;\n\tlet subscriber;\n\n\tconst createSubscriber = ( stores ) => {\n\t\t// The set of stores the `subscribe` function is supposed to subscribe to. Here it is\n\t\t// initialized, and then the `updateStores` function can add new stores to it.\n\t\tconst activeStores = [ ...stores ];\n\n\t\t// The `subscribe` function, which is passed to the `useSyncExternalStore` hook, could\n\t\t// be called multiple times to establish multiple subscriptions. That's why we need to\n\t\t// keep a set of active subscriptions;\n\t\tconst activeSubscriptions = new Set();\n\n\t\tfunction subscribe( listener ) {\n\t\t\t// Invalidate the value right after subscription was created. React will\n\t\t\t// call `getValue` after subscribing, to detect store updates that happened\n\t\t\t// in the interval between the `getValue` call during render and creating\n\t\t\t// the subscription, which is slightly delayed. We need to ensure that this\n\t\t\t// second `getValue` call will compute a fresh value.\n\t\t\tlastMapResultValid = false;\n\n\t\t\tconst onStoreChange = () => {\n\t\t\t\t// Invalidate the value on store update, so that a fresh value is computed.\n\t\t\t\tlastMapResultValid = false;\n\t\t\t\tlistener();\n\t\t\t};\n\n\t\t\tconst onChange = () => {\n\t\t\t\tif ( lastIsAsync ) {\n\t\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t\t} else {\n\t\t\t\t\tonStoreChange();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst unsubs = [];\n\t\t\tfunction subscribeStore( storeName ) {\n\t\t\t\tunsubs.push( registry.subscribe( onChange, storeName ) );\n\t\t\t}\n\n\t\t\tfor ( const storeName of activeStores ) {\n\t\t\t\tsubscribeStore( storeName );\n\t\t\t}\n\n\t\t\tactiveSubscriptions.add( subscribeStore );\n\n\t\t\treturn () => {\n\t\t\t\tactiveSubscriptions.delete( subscribeStore );\n\n\t\t\t\tfor ( const unsub of unsubs.values() ) {\n\t\t\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\t\t\tunsub?.();\n\t\t\t\t}\n\t\t\t\t// Cancel existing store updates that were already scheduled.\n\t\t\t\trenderQueue.cancel( queueContext );\n\t\t\t};\n\t\t}\n\n\t\t// Check if `newStores` contains some stores we're not subscribed to yet, and add them.\n\t\tfunction updateStores( newStores ) {\n\t\t\tfor ( const newStore of newStores ) {\n\t\t\t\tif ( activeStores.includes( newStore ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// New `subscribe` calls will subscribe to `newStore`, too.\n\t\t\t\tactiveStores.push( newStore );\n\n\t\t\t\t// Add `newStore` to existing subscriptions.\n\t\t\t\tfor ( const subscription of activeSubscriptions ) {\n\t\t\t\t\tsubscription( newStore );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { subscribe, updateStores };\n\t};\n\n\treturn ( mapSelect, isAsync ) => {\n\t\tfunction updateValue() {\n\t\t\t// If the last value is valid, and the `mapSelect` callback hasn't changed,\n\t\t\t// then we can safely return the cached value. The value can change only on\n\t\t\t// store update, and in that case value will be invalidated by the listener.\n\t\t\tif ( lastMapResultValid && mapSelect === lastMapSelect ) {\n\t\t\t\treturn lastMapResult;\n\t\t\t}\n\n\t\t\tconst listeningStores = { current: null };\n\t\t\tconst mapResult = registry.__unstableMarkListeningStores(\n\t\t\t\t() => mapSelect( select, registry ),\n\t\t\t\tlisteningStores\n\t\t\t);\n\n\t\t\tif ( ! subscriber ) {\n\t\t\t\tsubscriber = createSubscriber( listeningStores.current );\n\t\t\t} else {\n\t\t\t\tsubscriber.updateStores( listeningStores.current );\n\t\t\t}\n\n\t\t\t// If the new value is shallow-equal to the old one, keep the old one so\n\t\t\t// that we don't trigger unwanted updates that do a `===` check.\n\t\t\tif ( ! isShallowEqual( lastMapResult, mapResult ) ) {\n\t\t\t\tlastMapResult = mapResult;\n\t\t\t}\n\t\t\tlastMapSelect = mapSelect;\n\t\t\tlastMapResultValid = true;\n\t\t}\n\n\t\tfunction getValue() {\n\t\t\t// Update the value in case it's been invalidated or `mapSelect` has changed.\n\t\t\tupdateValue();\n\t\t\treturn lastMapResult;\n\t\t}\n\n\t\t// When transitioning from async to sync mode, cancel existing store updates\n\t\t// that have been scheduled, and invalidate the value so that it's freshly\n\t\t// computed. It might have been changed by the update we just cancelled.\n\t\tif ( lastIsAsync && ! isAsync ) {\n\t\t\tlastMapResultValid = false;\n\t\t\trenderQueue.cancel( queueContext );\n\t\t}\n\n\t\tupdateValue();\n\n\t\tlastIsAsync = isAsync;\n\n\t\t// Return a pair of functions that can be passed to `useSyncExternalStore`.\n\t\treturn { subscribe: subscriber.subscribe, getValue };\n\t};\n}\n\nfunction useStaticSelect( storeName ) {\n\treturn useRegistry().select( storeName );\n}\n\nfunction useMappingSelect( suspense, mapSelect, deps ) {\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\tconst store = useMemo( () => Store( registry, suspense ), [ registry ] );\n\tconst selector = useCallback( mapSelect, deps );\n\tconst { subscribe, getValue } = store( selector, isAsync );\n\tconst result = useSyncExternalStore( subscribe, getValue, getValue );\n\tuseDebugValue( result );\n\treturn result;\n}\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 * @template {MapSelect | StoreDescriptor<any>} T\n * @param {T} mapSelect Function called on every state change. The returned value is\n * exposed to the component implementing this hook. The function\n * receives the `registry.select` method on the first argument\n * and the `registry` on the second argument.\n * When a store key is passed, all selectors for the store will be\n * returned. This is only meant for usage of these selectors in event\n * callbacks, not for data needed to create the element tree.\n * @param {unknown[]} deps If provided, this memoizes the mapSelect so the same `mapSelect` is\n * invoked on every state change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n * import { store as myCustomStore } from 'my-custom-store';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( myCustomStore ).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 * import { store as myCustomStore } from 'my-custom-store';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( myCustomStore );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n * @return {UseSelectReturn<T>} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\t// On initial call, on mount, determine the mode of this `useSelect` call\n\t// and then never allow it to change on subsequent updates.\n\tconst staticSelectMode = typeof mapSelect !== 'function';\n\tconst staticSelectModeRef = useRef( staticSelectMode );\n\n\tif ( staticSelectMode !== staticSelectModeRef.current ) {\n\t\tconst prevMode = staticSelectModeRef.current ? 'static' : 'mapping';\n\t\tconst nextMode = staticSelectMode ? 'static' : 'mapping';\n\t\tthrow new Error(\n\t\t\t`Switching useSelect from ${ prevMode } to ${ nextMode } is not allowed`\n\t\t);\n\t}\n\n\t/* eslint-disable react-hooks/rules-of-hooks */\n\t// `staticSelectMode` is not allowed to change during the hook instance's,\n\t// lifetime, so the rules of hooks are not really violated.\n\treturn staticSelectMode\n\t\t? useStaticSelect( mapSelect )\n\t\t: useMappingSelect( false, mapSelect, deps );\n\t/* eslint-enable react-hooks/rules-of-hooks */\n}\n\n/**\n * A variant of the `useSelect` hook that has the same API, but will throw a\n * suspense Promise if any of the called selectors is in an unresolved state.\n *\n * @param {Function} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * using this hook. The function receives the\n * `registry.suspendSelect` method as the first\n * argument and the `registry` as the second one.\n * @param {Array} deps A dependency array used to memoize the `mapSelect`\n * so that the same `mapSelect` is invoked on every\n * state change unless the dependencies change.\n *\n * @return {Object} Data object returned by the `mapSelect` function.\n */\nexport function useSuspenseSelect( mapSelect, deps ) {\n\treturn useMappingSelect( true, mapSelect, deps );\n}\n"]}
package/build/registry.js CHANGED
@@ -240,12 +240,20 @@ function createRegistry() {
240
240
  /**
241
241
  * Registers a store instance.
242
242
  *
243
- * @param {string} name Store registry name.
244
- * @param {Object} store Store instance object (getSelectors, getActions, subscribe).
243
+ * @param {string} name Store registry name.
244
+ * @param {Function} createStore Function that creates a store object (getSelectors, getActions, subscribe).
245
245
  */
246
246
 
247
247
 
248
- function registerStoreInstance(name, store) {
248
+ function registerStoreInstance(name, createStore) {
249
+ if (stores[name]) {
250
+ // eslint-disable-next-line no-console
251
+ console.error('Store "' + name + '" is already registered.');
252
+ return stores[name];
253
+ }
254
+
255
+ const store = createStore();
256
+
249
257
  if (typeof store.getSelectors !== 'function') {
250
258
  throw new TypeError('store.getSelectors must be a function');
251
259
  }
@@ -292,6 +300,8 @@ function createRegistry() {
292
300
  // ignore it.
293
301
  }
294
302
  }
303
+
304
+ return store;
295
305
  }
296
306
  /**
297
307
  * Registers a new store given a store descriptor.
@@ -301,7 +311,7 @@ function createRegistry() {
301
311
 
302
312
 
303
313
  function register(store) {
304
- registerStoreInstance(store.name, store.instantiate(registry));
314
+ registerStoreInstance(store.name, () => store.instantiate(registry));
305
315
  }
306
316
 
307
317
  function registerGenericStore(name, store) {
@@ -309,7 +319,7 @@ function createRegistry() {
309
319
  since: '5.9',
310
320
  alternative: 'wp.data.register( storeDescriptor )'
311
321
  });
312
- registerStoreInstance(name, store);
322
+ registerStoreInstance(name, () => store);
313
323
  }
314
324
  /**
315
325
  * Registers a standard `@wordpress/data` store.
@@ -326,8 +336,7 @@ function createRegistry() {
326
336
  throw new TypeError('Must specify store reducer');
327
337
  }
328
338
 
329
- const store = (0, _reduxStore.default)(storeName, options).instantiate(registry);
330
- registerStoreInstance(storeName, store);
339
+ const store = registerStoreInstance(storeName, () => (0, _reduxStore.default)(storeName, options).instantiate(registry));
331
340
  return store.store;
332
341
  }
333
342