@wordpress/data 6.1.4 → 6.2.1
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 +18 -0
- package/LICENSE.md +1 -1
- package/README.md +77 -71
- package/build/components/use-dispatch/use-dispatch.js +8 -8
- package/build/components/use-dispatch/use-dispatch.js.map +1 -1
- package/build/components/use-select/index.js +58 -43
- package/build/components/use-select/index.js.map +1 -1
- package/build/controls.js +16 -16
- package/build/controls.js.map +1 -1
- package/build/index.js +14 -14
- package/build/index.js.map +1 -1
- package/build/plugins/index.js +0 -8
- package/build/plugins/index.js.map +1 -1
- package/build/redux-store/index.js +15 -15
- package/build/redux-store/index.js.map +1 -1
- package/build/registry.js +82 -68
- package/build/registry.js.map +1 -1
- package/build/resolvers-cache-middleware.js +5 -3
- package/build/resolvers-cache-middleware.js.map +1 -1
- package/build/store/index.js +42 -43
- package/build/store/index.js.map +1 -1
- package/build/utils/emitter.js +1 -1
- package/build/utils/emitter.js.map +1 -1
- package/build-module/components/use-dispatch/use-dispatch.js +8 -8
- package/build-module/components/use-dispatch/use-dispatch.js.map +1 -1
- package/build-module/components/use-select/index.js +60 -44
- package/build-module/components/use-select/index.js.map +1 -1
- package/build-module/controls.js +16 -16
- package/build-module/controls.js.map +1 -1
- package/build-module/index.js +14 -14
- package/build-module/index.js.map +1 -1
- package/build-module/plugins/index.js +0 -1
- package/build-module/plugins/index.js.map +1 -1
- package/build-module/redux-store/index.js +15 -15
- package/build-module/redux-store/index.js.map +1 -1
- package/build-module/registry.js +82 -68
- package/build-module/registry.js.map +1 -1
- package/build-module/resolvers-cache-middleware.js +3 -3
- package/build-module/resolvers-cache-middleware.js.map +1 -1
- package/build-module/store/index.js +42 -42
- package/build-module/store/index.js.map +1 -1
- package/build-module/utils/emitter.js +1 -1
- package/build-module/utils/emitter.js.map +1 -1
- package/build-types/types.d.ts +29 -16
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils/emitter.d.ts +2 -2
- package/build-types/utils/emitter.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/components/use-dispatch/test/use-dispatch.js +1 -1
- package/src/components/use-dispatch/use-dispatch.js +9 -9
- package/src/components/use-select/index.js +61 -46
- package/src/components/use-select/test/index.js +32 -32
- package/src/controls.js +22 -22
- package/src/index.js +14 -14
- package/src/plugins/index.js +0 -1
- package/src/redux-store/index.js +15 -15
- package/src/registry.js +88 -75
- package/src/resolvers-cache-middleware.js +3 -3
- package/src/store/index.js +49 -48
- package/src/test/registry.js +33 -47
- package/src/types.ts +44 -16
- package/src/utils/emitter.js +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/build/plugins/controls/index.js +0 -24
- package/build/plugins/controls/index.js.map +0 -1
- package/build/store/name.js +0 -15
- package/build/store/name.js.map +0 -1
- package/build-module/plugins/controls/index.js +0 -12
- package/build-module/plugins/controls/index.js.map +0 -1
- package/build-module/store/name.js +0 -7
- package/build-module/store/name.js.map +0 -1
- package/src/plugins/controls/index.js +0 -12
- package/src/store/name.js +0 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/data/src/utils/emitter.js"],"names":["createEmitter","isPaused","isPending","listeners","Set","notifyListeners","Array","from","forEach","listener","subscribe","add","delete","pause","resume","emit"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,aAAT,GAAyB;AAC/B,MAAIC,QAAQ,GAAG,KAAf;AACA,MAAIC,SAAS,GAAG,KAAhB;AACA,QAAMC,SAAS,GAAG,IAAIC,GAAJ,EAAlB;;AACA,QAAMC,eAAe,GAAG,MACvB;AACA;AACA;AACAC,EAAAA,KAAK,CAACC,IAAN,CAAYJ,SAAZ,EAAwBK,OAAxB,CAAmCC,QAAF,IAAgBA,QAAQ,EAAzD,CAJD;;AAMA,SAAO;AACN,QAAIR,QAAJ,GAAe;AACd,aAAOA,QAAP;AACA,KAHK;;AAKNS,IAAAA,SAAS,CAAED,QAAF,EAAa;AACrBN,MAAAA,SAAS,CAACQ,GAAV,CAAeF,QAAf;AACA,aAAO,MAAMN,SAAS,CAACS,MAAV,CAAkBH,QAAlB,CAAb;AACA,KARK;;AAUNI,IAAAA,KAAK,GAAG;AACPZ,MAAAA,QAAQ,GAAG,IAAX;AACA,KAZK;;AAcNa,IAAAA,MAAM,GAAG;AACRb,MAAAA,QAAQ,GAAG,KAAX;;AACA,UAAKC,SAAL,EAAiB;AAChBA,QAAAA,SAAS,GAAG,KAAZ;AACAG,QAAAA,eAAe;AACf;AACD,KApBK;;AAsBNU,IAAAA,IAAI,GAAG;AACN,UAAKd,QAAL,EAAgB;AACfC,QAAAA,SAAS,GAAG,IAAZ;AACA;AACA;;AACDG,MAAAA,eAAe;AACf;;AA5BK,GAAP;AA8BA","sourcesContent":["/**\n * Create an event emitter.\n *\n * @return {import(\"../types\").
|
|
1
|
+
{"version":3,"sources":["@wordpress/data/src/utils/emitter.js"],"names":["createEmitter","isPaused","isPending","listeners","Set","notifyListeners","Array","from","forEach","listener","subscribe","add","delete","pause","resume","emit"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,aAAT,GAAyB;AAC/B,MAAIC,QAAQ,GAAG,KAAf;AACA,MAAIC,SAAS,GAAG,KAAhB;AACA,QAAMC,SAAS,GAAG,IAAIC,GAAJ,EAAlB;;AACA,QAAMC,eAAe,GAAG,MACvB;AACA;AACA;AACAC,EAAAA,KAAK,CAACC,IAAN,CAAYJ,SAAZ,EAAwBK,OAAxB,CAAmCC,QAAF,IAAgBA,QAAQ,EAAzD,CAJD;;AAMA,SAAO;AACN,QAAIR,QAAJ,GAAe;AACd,aAAOA,QAAP;AACA,KAHK;;AAKNS,IAAAA,SAAS,CAAED,QAAF,EAAa;AACrBN,MAAAA,SAAS,CAACQ,GAAV,CAAeF,QAAf;AACA,aAAO,MAAMN,SAAS,CAACS,MAAV,CAAkBH,QAAlB,CAAb;AACA,KARK;;AAUNI,IAAAA,KAAK,GAAG;AACPZ,MAAAA,QAAQ,GAAG,IAAX;AACA,KAZK;;AAcNa,IAAAA,MAAM,GAAG;AACRb,MAAAA,QAAQ,GAAG,KAAX;;AACA,UAAKC,SAAL,EAAiB;AAChBA,QAAAA,SAAS,GAAG,KAAZ;AACAG,QAAAA,eAAe;AACf;AACD,KApBK;;AAsBNU,IAAAA,IAAI,GAAG;AACN,UAAKd,QAAL,EAAgB;AACfC,QAAAA,SAAS,GAAG,IAAZ;AACA;AACA;;AACDG,MAAAA,eAAe;AACf;;AA5BK,GAAP;AA8BA","sourcesContent":["/**\n * Create an event emitter.\n *\n * @return {import(\"../types\").DataEmitter} Emitter.\n */\nexport function createEmitter() {\n\tlet isPaused = false;\n\tlet isPending = false;\n\tconst listeners = new Set();\n\tconst notifyListeners = () =>\n\t\t// We use Array.from to clone the listeners Set\n\t\t// This ensures that we don't run a listener\n\t\t// that was added as a response to another listener.\n\t\tArray.from( listeners ).forEach( ( listener ) => listener() );\n\n\treturn {\n\t\tget isPaused() {\n\t\t\treturn isPaused;\n\t\t},\n\n\t\tsubscribe( listener ) {\n\t\t\tlisteners.add( listener );\n\t\t\treturn () => listeners.delete( listener );\n\t\t},\n\n\t\tpause() {\n\t\t\tisPaused = true;\n\t\t},\n\n\t\tresume() {\n\t\t\tisPaused = false;\n\t\t\tif ( isPending ) {\n\t\t\t\tisPending = false;\n\t\t\t\tnotifyListeners();\n\t\t\t}\n\t\t},\n\n\t\temit() {\n\t\t\tif ( isPaused ) {\n\t\t\t\tisPending = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnotifyListeners();\n\t\t},\n\t};\n}\n"]}
|
package/build-types/types.d.ts
CHANGED
|
@@ -1,35 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
declare type MapOf<T> = {
|
|
2
|
+
[name: string]: T;
|
|
3
|
+
};
|
|
4
|
+
export declare type ActionCreator = Function | Generator;
|
|
5
|
+
export declare type Resolver = Function | Generator;
|
|
6
|
+
export declare type Selector = Function;
|
|
7
|
+
export declare type AnyConfig = ReduxStoreConfig<any, any, any>;
|
|
8
|
+
export interface StoreInstance<Config extends AnyConfig> {
|
|
9
|
+
getSelectors: () => SelectorsOf<Config>;
|
|
10
|
+
getActions: () => ActionCreatorsOf<Config>;
|
|
6
11
|
subscribe: (listener: () => void) => () => void;
|
|
7
12
|
}
|
|
8
|
-
export interface
|
|
13
|
+
export interface StoreDescriptor<Config extends AnyConfig> {
|
|
9
14
|
/**
|
|
10
15
|
* Store Name
|
|
11
16
|
*/
|
|
12
17
|
name: string;
|
|
13
18
|
/**
|
|
14
|
-
*
|
|
19
|
+
* Creates a store instance
|
|
15
20
|
*/
|
|
16
|
-
instantiate: (registry:
|
|
21
|
+
instantiate: (registry: DataRegistry) => StoreInstance<Config>;
|
|
17
22
|
}
|
|
18
|
-
export interface
|
|
23
|
+
export interface ReduxStoreConfig<State, ActionCreators extends MapOf<ActionCreator>, Selectors extends MapOf<Selector>> {
|
|
24
|
+
initialState?: State;
|
|
19
25
|
reducer: (state: any, action: any) => any;
|
|
20
|
-
actions?:
|
|
21
|
-
resolvers?:
|
|
22
|
-
selectors?:
|
|
23
|
-
controls?:
|
|
26
|
+
actions?: ActionCreators;
|
|
27
|
+
resolvers?: MapOf<Resolver>;
|
|
28
|
+
selectors?: Selectors;
|
|
29
|
+
controls?: MapOf<Function>;
|
|
24
30
|
}
|
|
25
|
-
export interface
|
|
26
|
-
register: (store:
|
|
31
|
+
export interface DataRegistry {
|
|
32
|
+
register: (store: StoreDescriptor<any>) => void;
|
|
27
33
|
}
|
|
28
|
-
export interface
|
|
34
|
+
export interface DataEmitter {
|
|
29
35
|
emit: () => void;
|
|
30
36
|
subscribe: (listener: () => void) => () => void;
|
|
31
37
|
pause: () => void;
|
|
32
38
|
resume: () => void;
|
|
33
39
|
isPaused: boolean;
|
|
34
40
|
}
|
|
41
|
+
declare type ActionCreatorsOf<Config extends AnyConfig> = Config extends ReduxStoreConfig<any, infer ActionCreators, any> ? {
|
|
42
|
+
[name in keyof ActionCreators]: Function | Generator;
|
|
43
|
+
} : never;
|
|
44
|
+
declare type SelectorsOf<Config extends AnyConfig> = Config extends ReduxStoreConfig<any, any, infer Selectors> ? {
|
|
45
|
+
[name in keyof Selectors]: Function;
|
|
46
|
+
} : never;
|
|
47
|
+
export {};
|
|
35
48
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,oBAAY,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,aAAK,KAAK,CAAE,CAAC,IAAK;IAAE,CAAE,IAAI,EAAE,MAAM,GAAI,CAAC,CAAA;CAAE,CAAC;AAE1C,oBAAY,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AACjD,oBAAY,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC5C,oBAAY,QAAQ,GAAG,QAAQ,CAAC;AAEhC,oBAAY,SAAS,GAAG,gBAAgB,CAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAE,CAAC;AAE1D,MAAM,WAAW,aAAa,CAAE,MAAM,SAAS,SAAS;IACvD,YAAY,EAAE,MAAM,WAAW,CAAE,MAAM,CAAE,CAAC;IAC1C,UAAU,EAAE,MAAM,gBAAgB,CAAE,MAAM,CAAE,CAAC;IAC7C,SAAS,EAAE,CAAE,QAAQ,EAAE,MAAM,IAAI,KAAM,MAAM,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,eAAe,CAAE,MAAM,SAAS,SAAS;IACzD;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,CAAE,QAAQ,EAAE,YAAY,KAAM,aAAa,CAAE,MAAM,CAAE,CAAC;CACnE;AAED,MAAM,WAAW,gBAAgB,CAChC,KAAK,EACL,cAAc,SAAS,KAAK,CAAE,aAAa,CAAE,EAC7C,SAAS,SAAS,KAAK,CAAE,QAAQ,CAAE;IAEnC,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,OAAO,EAAE,CAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAM,GAAG,CAAC;IAC5C,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,KAAK,CAAE,QAAQ,CAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,KAAK,CAAE,QAAQ,CAAE,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,CAAE,KAAK,EAAE,eAAe,CAAE,GAAG,CAAE,KAAM,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,EAAE,CAAE,QAAQ,EAAE,MAAM,IAAI,KAAM,MAAM,IAAI,CAAC;IAClD,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CAClB;AAMD,aAAK,gBAAgB,CACpB,MAAM,SAAS,SAAS,IACrB,MAAM,SAAS,gBAAgB,CAAE,GAAG,EAAE,MAAM,cAAc,EAAE,GAAG,CAAE,GAClE;KAAI,IAAI,IAAI,MAAM,cAAc,GAAI,QAAQ,GAAG,SAAS;CAAE,GAC1D,KAAK,CAAC;AAET,aAAK,WAAW,CAAE,MAAM,SAAS,SAAS,IAAK,MAAM,SAAS,gBAAgB,CAC7E,GAAG,EACH,GAAG,EACH,MAAM,SAAS,CACf,GACE;KAAI,IAAI,IAAI,MAAM,SAAS,GAAI,QAAQ;CAAE,GACzC,KAAK,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Create an event emitter.
|
|
3
3
|
*
|
|
4
|
-
* @return {import("../types").
|
|
4
|
+
* @return {import("../types").DataEmitter} Emitter.
|
|
5
5
|
*/
|
|
6
|
-
export function createEmitter(): import("../types").
|
|
6
|
+
export function createEmitter(): import("../types").DataEmitter;
|
|
7
7
|
//# sourceMappingURL=emitter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/utils/emitter.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,iCAFY,OAAO,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/utils/emitter.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,iCAFY,OAAO,UAAU,EAAE,WAAW,CA0CzC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/data",
|
|
3
|
-
"version": "6.1
|
|
3
|
+
"version": "6.2.1",
|
|
4
4
|
"description": "Data module for WordPress.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -28,24 +28,24 @@
|
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@babel/runtime": "^7.16.0",
|
|
31
|
-
"@wordpress/compose": "^5.
|
|
32
|
-
"@wordpress/deprecated": "^3.
|
|
33
|
-
"@wordpress/element": "^4.
|
|
34
|
-
"@wordpress/is-shallow-equal": "^4.
|
|
35
|
-
"@wordpress/priority-queue": "^2.
|
|
36
|
-
"@wordpress/redux-routine": "^4.
|
|
31
|
+
"@wordpress/compose": "^5.1.1",
|
|
32
|
+
"@wordpress/deprecated": "^3.3.1",
|
|
33
|
+
"@wordpress/element": "^4.1.1",
|
|
34
|
+
"@wordpress/is-shallow-equal": "^4.3.1",
|
|
35
|
+
"@wordpress/priority-queue": "^2.3.1",
|
|
36
|
+
"@wordpress/redux-routine": "^4.3.1",
|
|
37
37
|
"equivalent-key-map": "^0.2.2",
|
|
38
38
|
"is-promise": "^4.0.0",
|
|
39
39
|
"lodash": "^4.17.21",
|
|
40
|
-
"
|
|
40
|
+
"redux": "^4.1.2",
|
|
41
41
|
"turbo-combine-reducers": "^1.0.2",
|
|
42
42
|
"use-memo-one": "^1.1.1"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"
|
|
45
|
+
"react": "^17.0.0"
|
|
46
46
|
},
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "2e4922861e49f5a090f9dc52056165092cfba163"
|
|
51
51
|
}
|
|
@@ -82,7 +82,7 @@ describe( 'useDispatch', () => {
|
|
|
82
82
|
expect( testAction ).toHaveBeenCalledTimes( 1 );
|
|
83
83
|
} );
|
|
84
84
|
|
|
85
|
-
it( 'returns expected action creators from store for given store
|
|
85
|
+
it( 'returns expected action creators from store for given store descriptor', () => {
|
|
86
86
|
const noop = () => ( { type: '__INERT__' } );
|
|
87
87
|
const testAction = jest.fn().mockImplementation( noop );
|
|
88
88
|
registry.registerStore( 'demoStore', {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import useRegistry from '../registry-provider/use-registry';
|
|
5
5
|
|
|
6
|
-
/** @typedef {import('
|
|
6
|
+
/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A custom react hook returning the current registry dispatch actions creators.
|
|
@@ -11,11 +11,11 @@ import useRegistry from '../registry-provider/use-registry';
|
|
|
11
11
|
* Note: The component using this hook must be within the context of a
|
|
12
12
|
* RegistryProvider.
|
|
13
13
|
*
|
|
14
|
-
* @param {string|
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
14
|
+
* @param {string|StoreDescriptor} [storeNameOrDescriptor] Optionally provide the name of the
|
|
15
|
+
* store or its descriptor from which to
|
|
16
|
+
* retrieve action creators. If not
|
|
17
|
+
* provided, the registry.dispatch
|
|
18
|
+
* function is returned instead.
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* This illustrates a pattern where you may need to retrieve dynamic data from
|
|
@@ -49,11 +49,11 @@ import useRegistry from '../registry-provider/use-registry';
|
|
|
49
49
|
* ```
|
|
50
50
|
* @return {Function} A custom react hook.
|
|
51
51
|
*/
|
|
52
|
-
const useDispatch = (
|
|
52
|
+
const useDispatch = ( storeNameOrDescriptor ) => {
|
|
53
53
|
const { dispatch } = useRegistry();
|
|
54
|
-
return
|
|
54
|
+
return storeNameOrDescriptor === void 0
|
|
55
55
|
? dispatch
|
|
56
|
-
: dispatch(
|
|
56
|
+
: dispatch( storeNameOrDescriptor );
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
export default useDispatch;
|
|
@@ -7,7 +7,7 @@ import { useMemoOne } from 'use-memo-one';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import { createQueue } from '@wordpress/priority-queue';
|
|
10
|
-
import { useRef, useCallback,
|
|
10
|
+
import { useRef, useCallback, useMemo, useReducer } from '@wordpress/element';
|
|
11
11
|
import isShallowEqual from '@wordpress/is-shallow-equal';
|
|
12
12
|
import { useIsomorphicLayoutEffect } from '@wordpress/compose';
|
|
13
13
|
|
|
@@ -17,9 +17,10 @@ import { useIsomorphicLayoutEffect } from '@wordpress/compose';
|
|
|
17
17
|
import useRegistry from '../registry-provider/use-registry';
|
|
18
18
|
import useAsyncMode from '../async-mode-provider/use-async-mode';
|
|
19
19
|
|
|
20
|
+
const noop = () => {};
|
|
20
21
|
const renderQueue = createQueue();
|
|
21
22
|
|
|
22
|
-
/** @typedef {import('
|
|
23
|
+
/** @typedef {import('../../types').StoreDescriptor} StoreDescriptor */
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Custom react hook for retrieving props from registered selectors.
|
|
@@ -27,20 +28,20 @@ const renderQueue = createQueue();
|
|
|
27
28
|
* In general, this custom React hook follows the
|
|
28
29
|
* [rules of hooks](https://reactjs.org/docs/hooks-rules.html).
|
|
29
30
|
*
|
|
30
|
-
* @param {Function|
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* @param {Array}
|
|
42
|
-
*
|
|
43
|
-
*
|
|
31
|
+
* @param {Function|StoreDescriptor|string} mapSelect Function called on every state change. The
|
|
32
|
+
* returned value is exposed to the component
|
|
33
|
+
* implementing this hook. The function receives
|
|
34
|
+
* the `registry.select` method on the first
|
|
35
|
+
* argument and the `registry` on the second
|
|
36
|
+
* argument.
|
|
37
|
+
* When a store key is passed, all selectors for
|
|
38
|
+
* the store will be returned. This is only meant
|
|
39
|
+
* for usage of these selectors in event
|
|
40
|
+
* callbacks, not for data needed to create the
|
|
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.
|
|
44
45
|
*
|
|
45
46
|
* @example
|
|
46
47
|
* ```js
|
|
@@ -88,14 +89,27 @@ const renderQueue = createQueue();
|
|
|
88
89
|
*
|
|
89
90
|
* @return {Function} A custom react hook.
|
|
90
91
|
*/
|
|
91
|
-
export default function useSelect(
|
|
92
|
-
const
|
|
92
|
+
export default function useSelect( mapSelect, deps ) {
|
|
93
|
+
const hasMappingFunction = 'function' === typeof mapSelect;
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
// If we're recalling a store by its name or by
|
|
96
|
+
// its descriptor then we won't be caching the
|
|
97
|
+
// calls to `mapSelect` because we won't be calling it.
|
|
98
|
+
if ( ! hasMappingFunction ) {
|
|
95
99
|
deps = [];
|
|
96
100
|
}
|
|
97
101
|
|
|
98
|
-
|
|
102
|
+
// Because of the "rule of hooks" we have to call `useCallback`
|
|
103
|
+
// on every invocation whether or not we have a real function
|
|
104
|
+
// for `mapSelect`. we'll create this intermediate variable to
|
|
105
|
+
// fulfill that need and then reference it with our "real"
|
|
106
|
+
// `_mapSelect` if we can.
|
|
107
|
+
const callbackMapper = useCallback(
|
|
108
|
+
hasMappingFunction ? mapSelect : noop,
|
|
109
|
+
deps
|
|
110
|
+
);
|
|
111
|
+
const _mapSelect = hasMappingFunction ? callbackMapper : null;
|
|
112
|
+
|
|
99
113
|
const registry = useRegistry();
|
|
100
114
|
const isAsync = useAsyncMode();
|
|
101
115
|
// React can sometimes clear the `useMemo` cache.
|
|
@@ -110,7 +124,7 @@ export default function useSelect( _mapSelect, deps ) {
|
|
|
110
124
|
const latestMapOutputError = useRef();
|
|
111
125
|
const isMountedAndNotUnsubscribing = useRef();
|
|
112
126
|
|
|
113
|
-
// Keep track of the stores being selected in the
|
|
127
|
+
// Keep track of the stores being selected in the _mapSelect function,
|
|
114
128
|
// and only subscribe to those stores later.
|
|
115
129
|
const listeningStores = useRef( [] );
|
|
116
130
|
const trapSelect = useCallback(
|
|
@@ -129,39 +143,37 @@ export default function useSelect( _mapSelect, deps ) {
|
|
|
129
143
|
|
|
130
144
|
let mapOutput;
|
|
131
145
|
|
|
132
|
-
if (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
146
|
+
if ( _mapSelect ) {
|
|
147
|
+
mapOutput = latestMapOutput.current;
|
|
148
|
+
const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;
|
|
149
|
+
const lastMapSelectFailed = !! latestMapOutputError.current;
|
|
150
|
+
|
|
151
|
+
if ( hasReplacedMapSelect || lastMapSelectFailed ) {
|
|
152
|
+
try {
|
|
138
153
|
mapOutput = trapSelect( () =>
|
|
139
|
-
|
|
154
|
+
_mapSelect( registry.select, registry )
|
|
140
155
|
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
} catch ( error ) {
|
|
145
|
-
let errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;
|
|
156
|
+
} catch ( error ) {
|
|
157
|
+
let errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;
|
|
146
158
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
159
|
+
if ( latestMapOutputError.current ) {
|
|
160
|
+
errorMessage += `\nThe error may be correlated with this previous error:\n`;
|
|
161
|
+
errorMessage += `${ latestMapOutputError.current.stack }\n\n`;
|
|
162
|
+
errorMessage += 'Original stack trace:';
|
|
163
|
+
}
|
|
152
164
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
165
|
+
// eslint-disable-next-line no-console
|
|
166
|
+
console.error( errorMessage );
|
|
167
|
+
}
|
|
156
168
|
}
|
|
157
169
|
}
|
|
158
170
|
|
|
159
171
|
useIsomorphicLayoutEffect( () => {
|
|
160
|
-
if (
|
|
172
|
+
if ( ! hasMappingFunction ) {
|
|
161
173
|
return;
|
|
162
174
|
}
|
|
163
175
|
|
|
164
|
-
latestMapSelect.current =
|
|
176
|
+
latestMapSelect.current = _mapSelect;
|
|
165
177
|
latestMapOutput.current = mapOutput;
|
|
166
178
|
latestMapOutputError.current = undefined;
|
|
167
179
|
isMountedAndNotUnsubscribing.current = true;
|
|
@@ -177,7 +189,7 @@ export default function useSelect( _mapSelect, deps ) {
|
|
|
177
189
|
} );
|
|
178
190
|
|
|
179
191
|
useIsomorphicLayoutEffect( () => {
|
|
180
|
-
if (
|
|
192
|
+
if ( ! hasMappingFunction ) {
|
|
181
193
|
return;
|
|
182
194
|
}
|
|
183
195
|
|
|
@@ -227,7 +239,10 @@ export default function useSelect( _mapSelect, deps ) {
|
|
|
227
239
|
unsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );
|
|
228
240
|
renderQueue.flush( queueContext );
|
|
229
241
|
};
|
|
230
|
-
|
|
242
|
+
// If you're tempted to eliminate the spread dependencies below don't do it!
|
|
243
|
+
// We're passing these in from the calling function and want to make sure we're
|
|
244
|
+
// examining every individual value inside the `deps` array.
|
|
245
|
+
}, [ registry, trapSelect, hasMappingFunction, depsChangedFlag ] );
|
|
231
246
|
|
|
232
|
-
return
|
|
247
|
+
return hasMappingFunction ? mapOutput : registry.select( mapSelect );
|
|
233
248
|
}
|
|
@@ -723,42 +723,42 @@ describe( 'useSelect', () => {
|
|
|
723
723
|
it( 'handles custom generic stores without a unsubscribe function', () => {
|
|
724
724
|
let renderer;
|
|
725
725
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
726
|
+
const customStore = {
|
|
727
|
+
name: 'generic-store',
|
|
728
|
+
instantiate() {
|
|
729
|
+
let storeChanged = () => {};
|
|
730
|
+
let counter = 0;
|
|
731
|
+
|
|
732
|
+
const selectors = {
|
|
733
|
+
getCounter: () => counter,
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
const actions = {
|
|
737
|
+
increment: () => {
|
|
738
|
+
counter += 1;
|
|
739
|
+
storeChanged();
|
|
740
|
+
},
|
|
741
|
+
};
|
|
740
742
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
743
|
+
return {
|
|
744
|
+
getSelectors() {
|
|
745
|
+
return selectors;
|
|
746
|
+
},
|
|
747
|
+
getActions() {
|
|
748
|
+
return actions;
|
|
749
|
+
},
|
|
750
|
+
subscribe( listener ) {
|
|
751
|
+
storeChanged = listener;
|
|
752
|
+
},
|
|
753
|
+
};
|
|
754
|
+
},
|
|
755
|
+
};
|
|
753
756
|
|
|
754
|
-
registry.
|
|
755
|
-
'generic-store',
|
|
756
|
-
createCustomStore()
|
|
757
|
-
);
|
|
757
|
+
registry.register( customStore );
|
|
758
758
|
|
|
759
759
|
const TestComponent = jest.fn( () => {
|
|
760
760
|
const state = useSelect(
|
|
761
|
-
( select ) => select(
|
|
761
|
+
( select ) => select( customStore ).getCounter(),
|
|
762
762
|
[]
|
|
763
763
|
);
|
|
764
764
|
|
|
@@ -778,7 +778,7 @@ describe( 'useSelect', () => {
|
|
|
778
778
|
expect( testInstance.findByType( 'div' ).props.data ).toBe( 0 );
|
|
779
779
|
|
|
780
780
|
act( () => {
|
|
781
|
-
registry.dispatch(
|
|
781
|
+
registry.dispatch( customStore ).increment();
|
|
782
782
|
} );
|
|
783
783
|
|
|
784
784
|
expect( testInstance.findByType( 'div' ).props.data ).toBe( 1 );
|
package/src/controls.js
CHANGED
|
@@ -8,7 +8,7 @@ import { isObject } from 'lodash';
|
|
|
8
8
|
*/
|
|
9
9
|
import { createRegistryControl } from './factory';
|
|
10
10
|
|
|
11
|
-
/** @typedef {import('./types').
|
|
11
|
+
/** @typedef {import('./types').StoreDescriptor} StoreDescriptor */
|
|
12
12
|
|
|
13
13
|
const SELECT = '@@data/SELECT';
|
|
14
14
|
const RESOLVE_SELECT = '@@data/RESOLVE_SELECT';
|
|
@@ -20,9 +20,9 @@ const DISPATCH = '@@data/DISPATCH';
|
|
|
20
20
|
* Note: This control synchronously returns the current selector value, triggering the
|
|
21
21
|
* resolution, but not waiting for it.
|
|
22
22
|
*
|
|
23
|
-
* @param {string|
|
|
24
|
-
* @param {string}
|
|
25
|
-
* @param {Array}
|
|
23
|
+
* @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store
|
|
24
|
+
* @param {string} selectorName The name of the selector.
|
|
25
|
+
* @param {Array} args Arguments for the selector.
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* ```js
|
|
@@ -37,12 +37,12 @@ const DISPATCH = '@@data/DISPATCH';
|
|
|
37
37
|
*
|
|
38
38
|
* @return {Object} The control descriptor.
|
|
39
39
|
*/
|
|
40
|
-
function select(
|
|
40
|
+
function select( storeNameOrDescriptor, selectorName, ...args ) {
|
|
41
41
|
return {
|
|
42
42
|
type: SELECT,
|
|
43
|
-
storeKey: isObject(
|
|
44
|
-
?
|
|
45
|
-
:
|
|
43
|
+
storeKey: isObject( storeNameOrDescriptor )
|
|
44
|
+
? storeNameOrDescriptor.name
|
|
45
|
+
: storeNameOrDescriptor,
|
|
46
46
|
selectorName,
|
|
47
47
|
args,
|
|
48
48
|
};
|
|
@@ -55,9 +55,9 @@ function select( storeNameOrDefinition, selectorName, ...args ) {
|
|
|
55
55
|
* selectors that may have a resolver. In such case, it will return a `Promise` that resolves
|
|
56
56
|
* after the selector finishes resolving, with the final result value.
|
|
57
57
|
*
|
|
58
|
-
* @param {string|
|
|
59
|
-
* @param {string}
|
|
60
|
-
* @param {Array}
|
|
58
|
+
* @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store
|
|
59
|
+
* @param {string} selectorName The name of the selector
|
|
60
|
+
* @param {Array} args Arguments for the selector.
|
|
61
61
|
*
|
|
62
62
|
* @example
|
|
63
63
|
* ```js
|
|
@@ -72,12 +72,12 @@ function select( storeNameOrDefinition, selectorName, ...args ) {
|
|
|
72
72
|
*
|
|
73
73
|
* @return {Object} The control descriptor.
|
|
74
74
|
*/
|
|
75
|
-
function resolveSelect(
|
|
75
|
+
function resolveSelect( storeNameOrDescriptor, selectorName, ...args ) {
|
|
76
76
|
return {
|
|
77
77
|
type: RESOLVE_SELECT,
|
|
78
|
-
storeKey: isObject(
|
|
79
|
-
?
|
|
80
|
-
:
|
|
78
|
+
storeKey: isObject( storeNameOrDescriptor )
|
|
79
|
+
? storeNameOrDescriptor.name
|
|
80
|
+
: storeNameOrDescriptor,
|
|
81
81
|
selectorName,
|
|
82
82
|
args,
|
|
83
83
|
};
|
|
@@ -86,9 +86,9 @@ function resolveSelect( storeNameOrDefinition, selectorName, ...args ) {
|
|
|
86
86
|
/**
|
|
87
87
|
* Dispatches a control action for triggering a registry dispatch.
|
|
88
88
|
*
|
|
89
|
-
* @param {string|
|
|
90
|
-
* @param {string}
|
|
91
|
-
* @param {Array}
|
|
89
|
+
* @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store
|
|
90
|
+
* @param {string} actionName The name of the action to dispatch
|
|
91
|
+
* @param {Array} args Arguments for the dispatch action.
|
|
92
92
|
*
|
|
93
93
|
* @example
|
|
94
94
|
* ```js
|
|
@@ -103,12 +103,12 @@ function resolveSelect( storeNameOrDefinition, selectorName, ...args ) {
|
|
|
103
103
|
*
|
|
104
104
|
* @return {Object} The control descriptor.
|
|
105
105
|
*/
|
|
106
|
-
function dispatch(
|
|
106
|
+
function dispatch( storeNameOrDescriptor, actionName, ...args ) {
|
|
107
107
|
return {
|
|
108
108
|
type: DISPATCH,
|
|
109
|
-
storeKey: isObject(
|
|
110
|
-
?
|
|
111
|
-
:
|
|
109
|
+
storeKey: isObject( storeNameOrDescriptor )
|
|
110
|
+
? storeNameOrDescriptor.name
|
|
111
|
+
: storeNameOrDescriptor,
|
|
112
112
|
actionName,
|
|
113
113
|
args,
|
|
114
114
|
};
|
package/src/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import combineReducers from 'turbo-combine-reducers';
|
|
|
9
9
|
import defaultRegistry from './default-registry';
|
|
10
10
|
import * as plugins from './plugins';
|
|
11
11
|
|
|
12
|
-
/** @typedef {import('./types').
|
|
12
|
+
/** @typedef {import('./types').StoreDescriptor} StoreDescriptor */
|
|
13
13
|
|
|
14
14
|
export { default as withSelect } from './components/with-select';
|
|
15
15
|
export { default as withDispatch } from './components/with-dispatch';
|
|
@@ -77,12 +77,12 @@ export { plugins };
|
|
|
77
77
|
export { combineReducers };
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
|
-
* Given the name or
|
|
80
|
+
* Given the name or descriptor of a registered store, returns an object of the store's selectors.
|
|
81
81
|
* The selector functions are been pre-bound to pass the current state automatically.
|
|
82
82
|
* As a consumer, you need only pass arguments of the selector, if applicable.
|
|
83
83
|
*
|
|
84
|
-
* @param {string|
|
|
85
|
-
*
|
|
84
|
+
* @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store
|
|
85
|
+
* or the store descriptor.
|
|
86
86
|
*
|
|
87
87
|
* @example
|
|
88
88
|
* ```js
|
|
@@ -101,8 +101,8 @@ export const select = defaultRegistry.select;
|
|
|
101
101
|
* and modified so that they return promises that resolve to their eventual values,
|
|
102
102
|
* after any resolvers have ran.
|
|
103
103
|
*
|
|
104
|
-
* @param {string|
|
|
105
|
-
*
|
|
104
|
+
* @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store
|
|
105
|
+
* or the store descriptor.
|
|
106
106
|
*
|
|
107
107
|
* @example
|
|
108
108
|
* ```js
|
|
@@ -122,8 +122,8 @@ export const resolveSelect = defaultRegistry.resolveSelect;
|
|
|
122
122
|
* Note: Action creators returned by the dispatch will return a promise when
|
|
123
123
|
* they are called.
|
|
124
124
|
*
|
|
125
|
-
* @param {string|
|
|
126
|
-
*
|
|
125
|
+
* @param {string|StoreDescriptor} storeNameOrDescriptor Unique namespace identifier for the store
|
|
126
|
+
* or the store descriptor.
|
|
127
127
|
*
|
|
128
128
|
* @example
|
|
129
129
|
* ```js
|
|
@@ -158,12 +158,12 @@ export const dispatch = defaultRegistry.dispatch;
|
|
|
158
158
|
export const subscribe = defaultRegistry.subscribe;
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
|
-
* Registers a generic store.
|
|
161
|
+
* Registers a generic store instance.
|
|
162
162
|
*
|
|
163
|
-
* @deprecated Use `register` instead.
|
|
163
|
+
* @deprecated Use `register( storeDescriptor )` instead.
|
|
164
164
|
*
|
|
165
|
-
* @param {string}
|
|
166
|
-
* @param {Object}
|
|
165
|
+
* @param {string} name Store registry name.
|
|
166
|
+
* @param {Object} store Store instance (`{ getSelectors, getActions, subscribe }`).
|
|
167
167
|
*/
|
|
168
168
|
export const registerGenericStore = defaultRegistry.registerGenericStore;
|
|
169
169
|
|
|
@@ -189,7 +189,7 @@ export const registerStore = defaultRegistry.registerStore;
|
|
|
189
189
|
export const use = defaultRegistry.use;
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
|
-
* Registers a standard `@wordpress/data` store
|
|
192
|
+
* Registers a standard `@wordpress/data` store descriptor.
|
|
193
193
|
*
|
|
194
194
|
* @example
|
|
195
195
|
* ```js
|
|
@@ -204,6 +204,6 @@ export const use = defaultRegistry.use;
|
|
|
204
204
|
* register( store );
|
|
205
205
|
* ```
|
|
206
206
|
*
|
|
207
|
-
* @param {
|
|
207
|
+
* @param {StoreDescriptor} store Store descriptor.
|
|
208
208
|
*/
|
|
209
209
|
export const register = defaultRegistry.register;
|