@wordpress/data 6.10.0 → 6.13.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 +10 -0
- package/README.md +55 -36
- package/build/components/async-mode-provider/context.js +2 -1
- package/build/components/async-mode-provider/context.js.map +1 -1
- package/build/components/use-dispatch/use-dispatch.js +3 -2
- package/build/components/use-dispatch/use-dispatch.js.map +1 -1
- package/build/components/use-select/index.js +32 -19
- package/build/components/use-select/index.js.map +1 -1
- package/build/components/with-dispatch/index.js +5 -3
- package/build/components/with-dispatch/index.js.map +1 -1
- package/build/components/with-registry/index.js.map +1 -1
- package/build/components/with-select/index.js +2 -1
- package/build/components/with-select/index.js.map +1 -1
- package/build/controls.js +8 -9
- package/build/controls.js.map +1 -1
- package/build/factory.js +5 -2
- package/build/factory.js.map +1 -1
- package/build/index.js +26 -20
- package/build/index.js.map +1 -1
- package/build/plugins/persistence/index.js.map +1 -1
- package/build/redux-store/index.js +14 -7
- package/build/redux-store/index.js.map +1 -1
- package/build/redux-store/metadata/utils.js.map +1 -1
- package/build/registry.js +21 -16
- package/build/registry.js.map +1 -1
- package/build/resolvers-cache-middleware.js.map +1 -1
- package/build/store/index.js.map +1 -1
- package/build-module/components/async-mode-provider/context.js +2 -1
- package/build-module/components/async-mode-provider/context.js.map +1 -1
- package/build-module/components/use-dispatch/use-dispatch.js +3 -2
- package/build-module/components/use-dispatch/use-dispatch.js.map +1 -1
- package/build-module/components/use-select/index.js +33 -20
- package/build-module/components/use-select/index.js.map +1 -1
- package/build-module/components/with-dispatch/index.js +5 -3
- package/build-module/components/with-dispatch/index.js.map +1 -1
- package/build-module/components/with-registry/index.js.map +1 -1
- package/build-module/components/with-select/index.js +2 -1
- package/build-module/components/with-select/index.js.map +1 -1
- package/build-module/controls.js +5 -5
- package/build-module/controls.js.map +1 -1
- package/build-module/factory.js +5 -2
- package/build-module/factory.js.map +1 -1
- package/build-module/index.js +26 -20
- package/build-module/index.js.map +1 -1
- package/build-module/plugins/persistence/index.js.map +1 -1
- package/build-module/redux-store/index.js +14 -7
- package/build-module/redux-store/index.js.map +1 -1
- package/build-module/redux-store/metadata/utils.js.map +1 -1
- package/build-module/registry.js +17 -12
- package/build-module/registry.js.map +1 -1
- package/build-module/resolvers-cache-middleware.js.map +1 -1
- package/build-module/store/index.js.map +1 -1
- package/build-types/components/async-mode-provider/context.d.ts +5 -0
- package/build-types/components/async-mode-provider/context.d.ts.map +1 -0
- package/build-types/components/async-mode-provider/index.d.ts +3 -0
- package/build-types/components/async-mode-provider/index.d.ts.map +1 -0
- package/build-types/components/async-mode-provider/use-async-mode.d.ts +2 -0
- package/build-types/components/async-mode-provider/use-async-mode.d.ts.map +1 -0
- package/build-types/components/registry-provider/context.d.ts +36 -0
- package/build-types/components/registry-provider/context.d.ts.map +1 -0
- package/build-types/components/registry-provider/index.d.ts +3 -0
- package/build-types/components/registry-provider/index.d.ts.map +1 -0
- package/build-types/components/registry-provider/use-registry.d.ts +41 -0
- package/build-types/components/registry-provider/use-registry.d.ts.map +1 -0
- package/build-types/components/use-dispatch/index.d.ts +3 -0
- package/build-types/components/use-dispatch/index.d.ts.map +1 -0
- package/build-types/components/use-dispatch/use-dispatch-with-map.d.ts +17 -0
- package/build-types/components/use-dispatch/use-dispatch-with-map.d.ts.map +1 -0
- package/build-types/components/use-dispatch/use-dispatch.d.ts +50 -0
- package/build-types/components/use-dispatch/use-dispatch.d.ts.map +1 -0
- package/build-types/components/use-select/index.d.ts +99 -0
- package/build-types/components/use-select/index.d.ts.map +1 -0
- package/build-types/components/with-dispatch/index.d.ts +84 -0
- package/build-types/components/with-dispatch/index.d.ts.map +1 -0
- package/build-types/components/with-registry/index.d.ts +11 -0
- package/build-types/components/with-registry/index.d.ts.map +1 -0
- package/build-types/components/with-select/index.d.ts +43 -0
- package/build-types/components/with-select/index.d.ts.map +1 -0
- package/build-types/controls.d.ts +83 -0
- package/build-types/controls.d.ts.map +1 -0
- package/build-types/default-registry.d.ts +3 -0
- package/build-types/default-registry.d.ts.map +1 -0
- package/build-types/factory.d.ts +63 -0
- package/build-types/factory.d.ts.map +1 -0
- package/build-types/index.d.ts +156 -0
- package/build-types/index.d.ts.map +1 -0
- package/build-types/plugins/index.d.ts +2 -0
- package/build-types/plugins/index.d.ts.map +1 -0
- package/build-types/plugins/persistence/index.d.ts +41 -0
- package/build-types/plugins/persistence/index.d.ts.map +1 -0
- package/build-types/plugins/persistence/storage/default.d.ts +3 -0
- package/build-types/plugins/persistence/storage/default.d.ts.map +1 -0
- package/build-types/plugins/persistence/storage/object.d.ts +10 -0
- package/build-types/plugins/persistence/storage/object.d.ts.map +1 -0
- package/build-types/redux-store/index.d.ts +29 -0
- package/build-types/redux-store/index.d.ts.map +1 -0
- package/build-types/redux-store/metadata/utils.d.ts.map +1 -1
- package/build-types/redux-store/thunk-middleware.d.ts +2 -0
- package/build-types/redux-store/thunk-middleware.d.ts.map +1 -0
- package/build-types/registry.d.ts +56 -0
- package/build-types/registry.d.ts.map +1 -0
- package/build-types/resolvers-cache-middleware.d.ts +15 -0
- package/build-types/resolvers-cache-middleware.d.ts.map +1 -0
- package/build-types/store/index.d.ts +23 -0
- package/build-types/store/index.d.ts.map +1 -0
- package/build-types/types.d.ts +18 -1
- package/build-types/types.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/components/async-mode-provider/context.js +2 -1
- package/src/components/use-dispatch/use-dispatch.js +3 -2
- package/src/components/use-select/index.js +37 -20
- package/src/components/use-select/test/suspense.js +15 -11
- package/src/components/with-dispatch/index.js +5 -3
- package/src/components/with-dispatch/test/index.js +4 -5
- package/src/components/with-registry/index.js +8 -7
- package/src/components/with-select/index.js +2 -1
- package/src/components/with-select/test/index.js +12 -18
- package/src/controls.js +20 -16
- package/src/factory.js +5 -2
- package/src/index.js +26 -20
- package/src/plugins/persistence/index.js +2 -4
- package/src/redux-store/index.js +22 -12
- package/src/redux-store/metadata/test/utils.js +1 -2
- package/src/redux-store/metadata/utils.ts +24 -24
- package/src/redux-store/test/index.js +4 -3
- package/src/registry.js +17 -12
- package/src/resolvers-cache-middleware.js +33 -34
- package/src/store/index.js +10 -6
- package/src/test/registry.js +19 -23
- package/src/types.ts +39 -6
- package/tsconfig.json +4 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -25,6 +25,7 @@ import useRegistry from '../registry-provider/use-registry';
|
|
|
25
25
|
* ```jsx
|
|
26
26
|
* import { useDispatch, useSelect } from '@wordpress/data';
|
|
27
27
|
* import { useCallback } from '@wordpress/element';
|
|
28
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
28
29
|
*
|
|
29
30
|
* function Button( { onClick, children } ) {
|
|
30
31
|
* return <button type="button" onClick={ onClick }>{ children }</button>
|
|
@@ -32,10 +33,10 @@ import useRegistry from '../registry-provider/use-registry';
|
|
|
32
33
|
*
|
|
33
34
|
* const SaleButton = ( { children } ) => {
|
|
34
35
|
* const { stockNumber } = useSelect(
|
|
35
|
-
* ( select ) => select(
|
|
36
|
+
* ( select ) => select( myCustomStore ).getStockNumber(),
|
|
36
37
|
* []
|
|
37
38
|
* );
|
|
38
|
-
* const { startSale } = useDispatch(
|
|
39
|
+
* const { startSale } = useDispatch( myCustomStore );
|
|
39
40
|
* const onClick = useCallback( () => {
|
|
40
41
|
* const discountPercent = stockNumber > 50 ? 10: 20;
|
|
41
42
|
* startSale( discountPercent );
|
|
@@ -7,7 +7,13 @@ import { useMemoOne } from 'use-memo-one';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import { createQueue } from '@wordpress/priority-queue';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
useRef,
|
|
12
|
+
useCallback,
|
|
13
|
+
useMemo,
|
|
14
|
+
useReducer,
|
|
15
|
+
useDebugValue,
|
|
16
|
+
} from '@wordpress/element';
|
|
11
17
|
import isShallowEqual from '@wordpress/is-shallow-equal';
|
|
12
18
|
import { useIsomorphicLayoutEffect } from '@wordpress/compose';
|
|
13
19
|
|
|
@@ -20,7 +26,19 @@ import useAsyncMode from '../async-mode-provider/use-async-mode';
|
|
|
20
26
|
const noop = () => {};
|
|
21
27
|
const renderQueue = createQueue();
|
|
22
28
|
|
|
23
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {import('../../types').StoreDescriptor<C>} StoreDescriptor
|
|
31
|
+
* @template C
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {import('../../types').ReduxStoreConfig<State,Actions,Selectors>} ReduxStoreConfig
|
|
35
|
+
* @template State,Actions,Selectors
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {import('../../types').UseSelectReturn<T>} UseSelectReturn
|
|
39
|
+
* @template T
|
|
40
|
+
*/
|
|
41
|
+
/** @typedef {import('../../types').MapSelect} MapSelect */
|
|
24
42
|
|
|
25
43
|
/**
|
|
26
44
|
* Custom react hook for retrieving props from registered selectors.
|
|
@@ -28,28 +46,25 @@ const renderQueue = createQueue();
|
|
|
28
46
|
* In general, this custom React hook follows the
|
|
29
47
|
* [rules of hooks](https://reactjs.org/docs/hooks-rules.html).
|
|
30
48
|
*
|
|
31
|
-
* @
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* element tree.
|
|
42
|
-
* @param {Array} deps If provided, this memoizes the mapSelect so the
|
|
43
|
-
* same `mapSelect` is invoked on every state
|
|
44
|
-
* change unless the dependencies change.
|
|
49
|
+
* @template {MapSelect | StoreDescriptor<any>} T
|
|
50
|
+
* @param {T} mapSelect Function called on every state change. The returned value is
|
|
51
|
+
* exposed to the component implementing this hook. The function
|
|
52
|
+
* receives the `registry.select` method on the first argument
|
|
53
|
+
* and the `registry` on the second argument.
|
|
54
|
+
* When a store key is passed, all selectors for the store will be
|
|
55
|
+
* returned. This is only meant for usage of these selectors in event
|
|
56
|
+
* callbacks, not for data needed to create the element tree.
|
|
57
|
+
* @param {unknown[]} deps If provided, this memoizes the mapSelect so the same `mapSelect` is
|
|
58
|
+
* invoked on every state change unless the dependencies change.
|
|
45
59
|
*
|
|
46
60
|
* @example
|
|
47
61
|
* ```js
|
|
48
62
|
* import { useSelect } from '@wordpress/data';
|
|
63
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
49
64
|
*
|
|
50
65
|
* function HammerPriceDisplay( { currency } ) {
|
|
51
66
|
* const price = useSelect( ( select ) => {
|
|
52
|
-
* return select(
|
|
67
|
+
* return select( myCustomStore ).getPrice( 'hammer', currency );
|
|
53
68
|
* }, [ currency ] );
|
|
54
69
|
* return new Intl.NumberFormat( 'en-US', {
|
|
55
70
|
* style: 'currency',
|
|
@@ -76,9 +91,10 @@ const renderQueue = createQueue();
|
|
|
76
91
|
*
|
|
77
92
|
* ```js
|
|
78
93
|
* import { useSelect } from '@wordpress/data';
|
|
94
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
79
95
|
*
|
|
80
96
|
* function Paste( { children } ) {
|
|
81
|
-
* const { getSettings } = useSelect(
|
|
97
|
+
* const { getSettings } = useSelect( myCustomStore );
|
|
82
98
|
* function onPaste() {
|
|
83
99
|
* // Do something with the settings.
|
|
84
100
|
* const settings = getSettings();
|
|
@@ -86,8 +102,7 @@ const renderQueue = createQueue();
|
|
|
86
102
|
* return <div onPaste={ onPaste }>{ children }</div>;
|
|
87
103
|
* }
|
|
88
104
|
* ```
|
|
89
|
-
*
|
|
90
|
-
* @return {Function} A custom react hook.
|
|
105
|
+
* @return {UseSelectReturn<T>} A custom react hook.
|
|
91
106
|
*/
|
|
92
107
|
export default function useSelect( mapSelect, deps ) {
|
|
93
108
|
const hasMappingFunction = 'function' === typeof mapSelect;
|
|
@@ -239,6 +254,8 @@ export default function useSelect( mapSelect, deps ) {
|
|
|
239
254
|
// examining every individual value inside the `deps` array.
|
|
240
255
|
}, [ registry, wrapSelect, hasMappingFunction, depsChangedFlag ] );
|
|
241
256
|
|
|
257
|
+
useDebugValue( mapOutput );
|
|
258
|
+
|
|
242
259
|
return hasMappingFunction ? mapOutput : registry.select( mapSelect );
|
|
243
260
|
}
|
|
244
261
|
|
|
@@ -50,17 +50,21 @@ function createRegistryWithStore() {
|
|
|
50
50
|
const sleep = ( ms ) => new Promise( ( r ) => setTimeout( () => r(), ms ) );
|
|
51
51
|
|
|
52
52
|
const resolvers = {
|
|
53
|
-
getToken:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
getToken:
|
|
54
|
+
() =>
|
|
55
|
+
async ( { dispatch } ) => {
|
|
56
|
+
await sleep( 10 );
|
|
57
|
+
dispatch( { type: 'RECEIVE_TOKEN', token: 'token' } );
|
|
58
|
+
},
|
|
59
|
+
getData:
|
|
60
|
+
( token ) =>
|
|
61
|
+
async ( { dispatch } ) => {
|
|
62
|
+
await sleep( 10 );
|
|
63
|
+
if ( ! token ) {
|
|
64
|
+
throw 'missing token in resolver';
|
|
65
|
+
}
|
|
66
|
+
dispatch( { type: 'RECEIVE_DATA', data: 'therealdata' } );
|
|
67
|
+
},
|
|
64
68
|
getThatFails: () => async () => {
|
|
65
69
|
await sleep( 10 );
|
|
66
70
|
throw 'resolution failed';
|
|
@@ -26,9 +26,10 @@ import { useDispatchWithMap } from '../use-dispatch';
|
|
|
26
26
|
* }
|
|
27
27
|
*
|
|
28
28
|
* import { withDispatch } from '@wordpress/data';
|
|
29
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
29
30
|
*
|
|
30
31
|
* const SaleButton = withDispatch( ( dispatch, ownProps ) => {
|
|
31
|
-
* const { startSale } = dispatch(
|
|
32
|
+
* const { startSale } = dispatch( myCustomStore );
|
|
32
33
|
* const { discountPercent } = ownProps;
|
|
33
34
|
*
|
|
34
35
|
* return {
|
|
@@ -63,11 +64,12 @@ import { useDispatchWithMap } from '../use-dispatch';
|
|
|
63
64
|
* }
|
|
64
65
|
*
|
|
65
66
|
* import { withDispatch } from '@wordpress/data';
|
|
67
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
66
68
|
*
|
|
67
69
|
* const SaleButton = withDispatch( ( dispatch, ownProps, { select } ) => {
|
|
68
70
|
* // Stock number changes frequently.
|
|
69
|
-
* const { getStockNumber } = select(
|
|
70
|
-
* const { startSale } = dispatch(
|
|
71
|
+
* const { getStockNumber } = select( myCustomStore );
|
|
72
|
+
* const { startSale } = dispatch( myCustomStore );
|
|
71
73
|
* return {
|
|
72
74
|
* onClick() {
|
|
73
75
|
* const discountPercent = getStockNumber() > 50 ? 10 : 20;
|
|
@@ -57,8 +57,8 @@ describe( 'withDispatch', () => {
|
|
|
57
57
|
} );
|
|
58
58
|
const testInstance = testRenderer.root;
|
|
59
59
|
|
|
60
|
-
const incrementBeforeSetProps =
|
|
61
|
-
.props.onClick;
|
|
60
|
+
const incrementBeforeSetProps =
|
|
61
|
+
testInstance.findByType( 'button' ).props.onClick;
|
|
62
62
|
|
|
63
63
|
// Verify that dispatch respects props at the time of being invoked by
|
|
64
64
|
// changing props after the initial mount.
|
|
@@ -194,9 +194,8 @@ describe( 'withDispatch', () => {
|
|
|
194
194
|
);
|
|
195
195
|
} );
|
|
196
196
|
|
|
197
|
-
const counterUpdateHandler =
|
|
198
|
-
'button'
|
|
199
|
-
).props.onClick;
|
|
197
|
+
const counterUpdateHandler =
|
|
198
|
+
testRenderer.root.findByType( 'button' ).props.onClick;
|
|
200
199
|
|
|
201
200
|
act( () => {
|
|
202
201
|
counterUpdateHandler();
|
|
@@ -17,13 +17,14 @@ import { RegistryConsumer } from '../registry-provider';
|
|
|
17
17
|
* @return {WPComponent} Enhanced component.
|
|
18
18
|
*/
|
|
19
19
|
const withRegistry = createHigherOrderComponent(
|
|
20
|
-
( OriginalComponent ) => ( props ) =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
( OriginalComponent ) => ( props ) =>
|
|
21
|
+
(
|
|
22
|
+
<RegistryConsumer>
|
|
23
|
+
{ ( registry ) => (
|
|
24
|
+
<OriginalComponent { ...props } registry={ registry } />
|
|
25
|
+
) }
|
|
26
|
+
</RegistryConsumer>
|
|
27
|
+
),
|
|
27
28
|
'withRegistry'
|
|
28
29
|
);
|
|
29
30
|
|
|
@@ -19,6 +19,7 @@ import useSelect from '../use-select';
|
|
|
19
19
|
* @example
|
|
20
20
|
* ```js
|
|
21
21
|
* import { withSelect } from '@wordpress/data';
|
|
22
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
22
23
|
*
|
|
23
24
|
* function PriceDisplay( { price, currency } ) {
|
|
24
25
|
* return new Intl.NumberFormat( 'en-US', {
|
|
@@ -28,7 +29,7 @@ import useSelect from '../use-select';
|
|
|
28
29
|
* }
|
|
29
30
|
*
|
|
30
31
|
* const HammerPriceDisplay = withSelect( ( select, ownProps ) => {
|
|
31
|
-
* const { getPrice } = select(
|
|
32
|
+
* const { getPrice } = select( myCustomStore );
|
|
32
33
|
* const { currency } = ownProps;
|
|
33
34
|
*
|
|
34
35
|
* return {
|
|
@@ -50,9 +50,8 @@ describe( 'withSelect', () => {
|
|
|
50
50
|
.fn()
|
|
51
51
|
.mockImplementation( ( props ) => <div>{ props.data }</div> );
|
|
52
52
|
|
|
53
|
-
const DataBoundComponent =
|
|
54
|
-
OriginalComponent
|
|
55
|
-
);
|
|
53
|
+
const DataBoundComponent =
|
|
54
|
+
withSelect( mapSelectToProps )( OriginalComponent );
|
|
56
55
|
let testRenderer;
|
|
57
56
|
act( () => {
|
|
58
57
|
testRenderer = TestRenderer.create(
|
|
@@ -268,9 +267,8 @@ describe( 'withSelect', () => {
|
|
|
268
267
|
.fn()
|
|
269
268
|
.mockImplementation( ( props ) => <div>{ props.count }</div> );
|
|
270
269
|
|
|
271
|
-
const DataBoundComponent =
|
|
272
|
-
OriginalComponent
|
|
273
|
-
);
|
|
270
|
+
const DataBoundComponent =
|
|
271
|
+
withSelect( mapSelectToProps )( OriginalComponent );
|
|
274
272
|
|
|
275
273
|
let testRenderer;
|
|
276
274
|
act( () => {
|
|
@@ -367,9 +365,8 @@ describe( 'withSelect', () => {
|
|
|
367
365
|
|
|
368
366
|
const OriginalComponent = jest.fn().mockImplementation( () => <div /> );
|
|
369
367
|
|
|
370
|
-
const DataBoundComponent =
|
|
371
|
-
OriginalComponent
|
|
372
|
-
);
|
|
368
|
+
const DataBoundComponent =
|
|
369
|
+
withSelect( mapSelectToProps )( OriginalComponent );
|
|
373
370
|
|
|
374
371
|
act( () => {
|
|
375
372
|
TestRenderer.create(
|
|
@@ -492,9 +489,8 @@ describe( 'withSelect', () => {
|
|
|
492
489
|
<div>{ JSON.stringify( props ) }</div>
|
|
493
490
|
) );
|
|
494
491
|
|
|
495
|
-
const DataBoundComponent =
|
|
496
|
-
OriginalComponent
|
|
497
|
-
);
|
|
492
|
+
const DataBoundComponent =
|
|
493
|
+
withSelect( mapSelectToProps )( OriginalComponent );
|
|
498
494
|
|
|
499
495
|
let testRenderer;
|
|
500
496
|
act( () => {
|
|
@@ -561,9 +557,8 @@ describe( 'withSelect', () => {
|
|
|
561
557
|
<div>{ props.count || 'Unknown' }</div>
|
|
562
558
|
) );
|
|
563
559
|
|
|
564
|
-
const DataBoundComponent =
|
|
565
|
-
OriginalComponent
|
|
566
|
-
);
|
|
560
|
+
const DataBoundComponent =
|
|
561
|
+
withSelect( mapSelectToProps )( OriginalComponent );
|
|
567
562
|
|
|
568
563
|
let testRenderer;
|
|
569
564
|
act( () => {
|
|
@@ -691,9 +686,8 @@ describe( 'withSelect', () => {
|
|
|
691
686
|
.fn()
|
|
692
687
|
.mockImplementation( ( props ) => <div>{ props.value }</div> );
|
|
693
688
|
|
|
694
|
-
const DataBoundComponent =
|
|
695
|
-
OriginalComponent
|
|
696
|
-
);
|
|
689
|
+
const DataBoundComponent =
|
|
690
|
+
withSelect( mapSelectToProps )( OriginalComponent );
|
|
697
691
|
|
|
698
692
|
let testRenderer;
|
|
699
693
|
act( () => {
|
package/src/controls.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { isObject } from 'lodash';
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Internal dependencies
|
|
8
3
|
*/
|
|
@@ -14,6 +9,10 @@ const SELECT = '@@data/SELECT';
|
|
|
14
9
|
const RESOLVE_SELECT = '@@data/RESOLVE_SELECT';
|
|
15
10
|
const DISPATCH = '@@data/DISPATCH';
|
|
16
11
|
|
|
12
|
+
function isObject( object ) {
|
|
13
|
+
return object !== null && typeof object === 'object';
|
|
14
|
+
}
|
|
15
|
+
|
|
17
16
|
/**
|
|
18
17
|
* Dispatches a control action for triggering a synchronous registry select.
|
|
19
18
|
*
|
|
@@ -118,20 +117,25 @@ export const controls = { select, resolveSelect, dispatch };
|
|
|
118
117
|
|
|
119
118
|
export const builtinControls = {
|
|
120
119
|
[ SELECT ]: createRegistryControl(
|
|
121
|
-
( registry ) =>
|
|
122
|
-
|
|
120
|
+
( registry ) =>
|
|
121
|
+
( { storeKey, selectorName, args } ) =>
|
|
122
|
+
registry.select( storeKey )[ selectorName ]( ...args )
|
|
123
123
|
),
|
|
124
124
|
[ RESOLVE_SELECT ]: createRegistryControl(
|
|
125
|
-
( registry ) =>
|
|
126
|
-
|
|
127
|
-
.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
125
|
+
( registry ) =>
|
|
126
|
+
( { storeKey, selectorName, args } ) => {
|
|
127
|
+
const method = registry.select( storeKey )[ selectorName ]
|
|
128
|
+
.hasResolver
|
|
129
|
+
? 'resolveSelect'
|
|
130
|
+
: 'select';
|
|
131
|
+
return registry[ method ]( storeKey )[ selectorName ](
|
|
132
|
+
...args
|
|
133
|
+
);
|
|
134
|
+
}
|
|
132
135
|
),
|
|
133
136
|
[ DISPATCH ]: createRegistryControl(
|
|
134
|
-
( registry ) =>
|
|
135
|
-
|
|
137
|
+
( registry ) =>
|
|
138
|
+
( { storeKey, actionName, args } ) =>
|
|
139
|
+
registry.dispatch( storeKey )[ actionName ]( ...args )
|
|
136
140
|
),
|
|
137
141
|
};
|
package/src/factory.js
CHANGED
|
@@ -13,15 +13,18 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```js
|
|
16
|
+
* import { store as coreStore } from '@wordpress/core-data';
|
|
17
|
+
* import { store as editorStore } from '@wordpress/editor';
|
|
18
|
+
*
|
|
16
19
|
* const getCurrentPostId = createRegistrySelector( ( select ) => ( state ) => {
|
|
17
|
-
* return select(
|
|
20
|
+
* return select( editorStore ).getCurrentPostId();
|
|
18
21
|
* } );
|
|
19
22
|
*
|
|
20
23
|
* const getPostEdits = createRegistrySelector( ( select ) => ( state ) => {
|
|
21
24
|
* // calling another registry selector just like any other function
|
|
22
25
|
* const postType = getCurrentPostType( state );
|
|
23
26
|
* const postId = getCurrentPostId( state );
|
|
24
|
-
* return select(
|
|
27
|
+
* return select( coreStore ).getEntityRecordEdits( 'postType', postType, postId );
|
|
25
28
|
* } );
|
|
26
29
|
* ```
|
|
27
30
|
*
|
package/src/index.js
CHANGED
|
@@ -80,18 +80,20 @@ export { plugins };
|
|
|
80
80
|
export { combineReducers };
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
|
-
* Given
|
|
83
|
+
* Given a store descriptor, returns an object of the store's selectors.
|
|
84
84
|
* The selector functions are been pre-bound to pass the current state automatically.
|
|
85
85
|
* As a consumer, you need only pass arguments of the selector, if applicable.
|
|
86
86
|
*
|
|
87
|
-
* @param {string
|
|
88
|
-
*
|
|
87
|
+
* @param {StoreDescriptor|string} storeNameOrDescriptor The store descriptor. The legacy calling
|
|
88
|
+
* convention of passing the store name is
|
|
89
|
+
* also supported.
|
|
89
90
|
*
|
|
90
91
|
* @example
|
|
91
92
|
* ```js
|
|
92
93
|
* import { select } from '@wordpress/data';
|
|
94
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
93
95
|
*
|
|
94
|
-
* select(
|
|
96
|
+
* select( myCustomStore ).getPrice( 'hammer' );
|
|
95
97
|
* ```
|
|
96
98
|
*
|
|
97
99
|
* @return {Object} Object containing the store's selectors.
|
|
@@ -99,19 +101,20 @@ export { combineReducers };
|
|
|
99
101
|
export const select = defaultRegistry.select;
|
|
100
102
|
|
|
101
103
|
/**
|
|
102
|
-
* Given
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* after any resolvers have ran.
|
|
104
|
+
* Given a store descriptor, returns an object containing the store's selectors pre-bound to state
|
|
105
|
+
* so that you only need to supply additional arguments, and modified so that they return promises
|
|
106
|
+
* that resolve to their eventual values, after any resolvers have ran.
|
|
106
107
|
*
|
|
107
|
-
* @param {string
|
|
108
|
-
*
|
|
108
|
+
* @param {StoreDescriptor|string} storeNameOrDescriptor The store descriptor. The legacy calling
|
|
109
|
+
* convention of passing the store name is
|
|
110
|
+
* also supported.
|
|
109
111
|
*
|
|
110
112
|
* @example
|
|
111
113
|
* ```js
|
|
112
114
|
* import { resolveSelect } from '@wordpress/data';
|
|
115
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
113
116
|
*
|
|
114
|
-
* resolveSelect(
|
|
117
|
+
* resolveSelect( myCustomStore ).getPrice( 'hammer' ).then(console.log)
|
|
115
118
|
* ```
|
|
116
119
|
*
|
|
117
120
|
* @return {Object} Object containing the store's promise-wrapped selectors.
|
|
@@ -119,32 +122,35 @@ export const select = defaultRegistry.select;
|
|
|
119
122
|
export const resolveSelect = defaultRegistry.resolveSelect;
|
|
120
123
|
|
|
121
124
|
/**
|
|
122
|
-
* Given
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
+
* Given a store descriptor, returns an object containing the store's selectors pre-bound to state
|
|
126
|
+
* so that you only need to supply additional arguments, and modified so that they throw promises
|
|
127
|
+
* in case the selector is not resolved yet.
|
|
125
128
|
*
|
|
126
|
-
* @param {string
|
|
127
|
-
*
|
|
129
|
+
* @param {StoreDescriptor|string} storeNameOrDescriptor The store descriptor. The legacy calling
|
|
130
|
+
* convention of passing the store name is
|
|
131
|
+
* also supported.
|
|
128
132
|
*
|
|
129
133
|
* @return {Object} Object containing the store's suspense-wrapped selectors.
|
|
130
134
|
*/
|
|
131
135
|
export const suspendSelect = defaultRegistry.suspendSelect;
|
|
132
136
|
|
|
133
137
|
/**
|
|
134
|
-
* Given
|
|
138
|
+
* Given a store descriptor, returns an object of the store's action creators.
|
|
135
139
|
* Calling an action creator will cause it to be dispatched, updating the state value accordingly.
|
|
136
140
|
*
|
|
137
141
|
* Note: Action creators returned by the dispatch will return a promise when
|
|
138
142
|
* they are called.
|
|
139
143
|
*
|
|
140
|
-
* @param {string
|
|
141
|
-
*
|
|
144
|
+
* @param {StoreDescriptor|string} storeNameOrDescriptor The store descriptor. The legacy calling
|
|
145
|
+
* convention of passing the store name is
|
|
146
|
+
* also supported.
|
|
142
147
|
*
|
|
143
148
|
* @example
|
|
144
149
|
* ```js
|
|
145
150
|
* import { dispatch } from '@wordpress/data';
|
|
151
|
+
* import { store as myCustomStore } from 'my-custom-store';
|
|
146
152
|
*
|
|
147
|
-
* dispatch(
|
|
153
|
+
* dispatch( myCustomStore ).setPrice( 'hammer', 9.75 );
|
|
148
154
|
* ```
|
|
149
155
|
* @return {Object} Object containing the action creators.
|
|
150
156
|
*/
|
|
@@ -63,10 +63,8 @@ export const withLazySameState = ( reducer ) => ( state, action ) => {
|
|
|
63
63
|
* @return {Object} Persistence interface.
|
|
64
64
|
*/
|
|
65
65
|
export function createPersistenceInterface( options ) {
|
|
66
|
-
const {
|
|
67
|
-
|
|
68
|
-
storageKey = DEFAULT_STORAGE_KEY,
|
|
69
|
-
} = options;
|
|
66
|
+
const { storage = DEFAULT_STORAGE, storageKey = DEFAULT_STORAGE_KEY } =
|
|
67
|
+
options;
|
|
70
68
|
|
|
71
69
|
let data;
|
|
72
70
|
|
package/src/redux-store/index.js
CHANGED
|
@@ -23,8 +23,14 @@ import * as metadataSelectors from './metadata/selectors';
|
|
|
23
23
|
import * as metadataActions from './metadata/actions';
|
|
24
24
|
|
|
25
25
|
/** @typedef {import('../types').DataRegistry} DataRegistry */
|
|
26
|
-
/**
|
|
27
|
-
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {import('../types').StoreDescriptor<C>} StoreDescriptor
|
|
28
|
+
* @template C
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {import('../types').ReduxStoreConfig<State,Actions,Selectors>} ReduxStoreConfig
|
|
32
|
+
* @template State,Actions,Selectors
|
|
33
|
+
*/
|
|
28
34
|
|
|
29
35
|
const trimUndefinedValues = ( array ) => {
|
|
30
36
|
const result = [ ...array ];
|
|
@@ -83,12 +89,13 @@ function createResolversCache() {
|
|
|
83
89
|
* } );
|
|
84
90
|
* ```
|
|
85
91
|
*
|
|
86
|
-
* @
|
|
87
|
-
* @param {
|
|
88
|
-
*
|
|
89
|
-
*
|
|
92
|
+
* @template State,Actions,Selectors
|
|
93
|
+
* @param {string} key Unique namespace identifier.
|
|
94
|
+
* @param {ReduxStoreConfig<State,Actions,Selectors>} options Registered store options, with properties
|
|
95
|
+
* describing reducer, actions, selectors,
|
|
96
|
+
* and resolvers.
|
|
90
97
|
*
|
|
91
|
-
* @return
|
|
98
|
+
* @return {StoreDescriptor<ReduxStoreConfig<State,Actions,Selectors>>} Store Object.
|
|
92
99
|
*/
|
|
93
100
|
export default function createReduxStore( key, options ) {
|
|
94
101
|
return {
|
|
@@ -136,8 +143,9 @@ export default function createReduxStore( key, options ) {
|
|
|
136
143
|
{
|
|
137
144
|
...mapValues(
|
|
138
145
|
metadataSelectors,
|
|
139
|
-
( selector ) =>
|
|
140
|
-
|
|
146
|
+
( selector ) =>
|
|
147
|
+
( state, ...args ) =>
|
|
148
|
+
selector( state.metadata, ...args )
|
|
141
149
|
),
|
|
142
150
|
...mapValues( options.selectors, ( selector ) => {
|
|
143
151
|
if ( selector.isRegistrySelector ) {
|
|
@@ -308,9 +316,11 @@ function mapSelectors( selectors, store ) {
|
|
|
308
316
|
* @return {Object} Actions mapped to the redux store provided.
|
|
309
317
|
*/
|
|
310
318
|
function mapActions( actions, store ) {
|
|
311
|
-
const createBoundAction =
|
|
312
|
-
|
|
313
|
-
|
|
319
|
+
const createBoundAction =
|
|
320
|
+
( action ) =>
|
|
321
|
+
( ...args ) => {
|
|
322
|
+
return Promise.resolve( store.dispatch( action( ...args ) ) );
|
|
323
|
+
};
|
|
314
324
|
|
|
315
325
|
return mapValues( actions, createBoundAction );
|
|
316
326
|
}
|
|
@@ -47,8 +47,7 @@ describe( 'selectorArgsToStateKey', () => {
|
|
|
47
47
|
|
|
48
48
|
it( 'should remove trailing undefined values', () => {
|
|
49
49
|
expect( selectorArgsToStateKey( [ 1, 2, undefined ] ) ).toEqual( [
|
|
50
|
-
1,
|
|
51
|
-
2,
|
|
50
|
+
1, 2,
|
|
52
51
|
] );
|
|
53
52
|
expect(
|
|
54
53
|
selectorArgsToStateKey( [ 1, 2, undefined, undefined ] )
|
|
@@ -10,33 +10,33 @@ import type { AnyAction, Reducer } from 'redux';
|
|
|
10
10
|
* @param actionProperty Action property by which to key object.
|
|
11
11
|
* @return Higher-order reducer.
|
|
12
12
|
*/
|
|
13
|
-
export const onSubKey =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
export const onSubKey =
|
|
14
|
+
< TState extends unknown, TAction extends AnyAction >(
|
|
15
|
+
actionProperty: string
|
|
16
|
+
) =>
|
|
17
|
+
(
|
|
18
|
+
reducer: Reducer< TState, TAction >
|
|
19
|
+
): Reducer< Record< string, TState >, TAction > =>
|
|
20
|
+
( state: Record< string, TState > = {}, action ) => {
|
|
21
|
+
// Retrieve subkey from action. Do not track if undefined; useful for cases
|
|
22
|
+
// where reducer is scoped by action shape.
|
|
23
|
+
const key = action[ actionProperty ];
|
|
24
|
+
if ( key === undefined ) {
|
|
25
|
+
return state;
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
// Avoid updating state if unchanged. Note that this also accounts for a
|
|
29
|
+
// reducer which returns undefined on a key which is not yet tracked.
|
|
30
|
+
const nextKeyState = reducer( state[ key ], action );
|
|
31
|
+
if ( nextKeyState === state[ key ] ) {
|
|
32
|
+
return state;
|
|
33
|
+
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
return {
|
|
36
|
+
...state,
|
|
37
|
+
[ key ]: nextKeyState,
|
|
38
|
+
};
|
|
38
39
|
};
|
|
39
|
-
};
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Normalize selector argument array by defaulting `undefined` value to an empty array
|