Skip to content

Commit 2a77bb2

Browse files
committed
Data: allow binding registry selector to multiple registries
1 parent 8b5bc0e commit 2a77bb2

File tree

3 files changed

+37
-8
lines changed

3 files changed

+37
-8
lines changed

packages/data/src/factory.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,22 @@
3939
* @return {Function} Registry selector that can be registered with a store.
4040
*/
4141
export function createRegistrySelector( registrySelector ) {
42-
let selector;
43-
let lastRegistry;
42+
const selectorsByRegistry = new WeakMap();
4443
// Create a selector function that is bound to the registry referenced by `selector.registry`
4544
// and that has the same API as a regular selector. Binding it in such a way makes it
4645
// possible to call the selector directly from another selector.
4746
const wrappedSelector = ( ...args ) => {
48-
if ( ! selector || lastRegistry !== wrappedSelector.registry ) {
49-
selector = registrySelector( wrappedSelector.registry.select );
50-
lastRegistry = wrappedSelector.registry;
47+
// We want to make sure the cache persists even when new registry
48+
// instances are created. For example patterns create their own editors
49+
// with their own core/block-editor stores, so we should keep track of
50+
// the cache for each registry instance.
51+
if ( ! selectorsByRegistry.has( wrappedSelector.registry ) ) {
52+
selectorsByRegistry.set(
53+
wrappedSelector.registry,
54+
registrySelector( wrappedSelector.registry.select )
55+
);
5156
}
52-
return selector( ...args );
57+
return selectorsByRegistry.get( wrappedSelector.registry )( ...args );
5358
};
5459

5560
/**

packages/data/src/redux-store/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ export default function createReduxStore( key, options ) {
237237
const boundSelector = ( ...args ) => {
238238
args = normalize( selector, args );
239239
const state = store.__unstableOriginalGetState();
240+
// Before calling the selector, switch to the correct
241+
// registry.
242+
if ( selector.isRegistrySelector ) {
243+
selector.registry = registry;
244+
}
240245
return selector( state.root, ...args );
241246
};
242247

packages/data/src/test/registry-selectors.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ describe( 'createRegistrySelector', () => {
7878
expect( registry.select( uiStore ).getElementCount() ).toBe( 1 );
7979
} );
8080

81-
// Even without createSelector, this fails in trunk.
82-
it.skip( 'can bind one selector to multiple registries', () => {
81+
it( 'can bind one selector to multiple registries (createRegistrySelector)', () => {
8382
const registry1 = createRegistry();
8483
const registry2 = createRegistry();
8584

@@ -102,6 +101,26 @@ describe( 'createRegistrySelector', () => {
102101
expect( registry2.select( uiStore ).getElementCount() ).toBe( 1 );
103102
} );
104103

104+
it( 'can bind one selector to multiple registries (createRegistrySelector + createSelector)', () => {
105+
const registry1 = createRegistry();
106+
registry1.register( elementsStore );
107+
registry1.register( uiStore );
108+
registry1.dispatch( elementsStore ).add( 'Carbon' );
109+
110+
const registry2 = createRegistry();
111+
registry2.register( elementsStore );
112+
registry2.register( uiStore );
113+
registry2.dispatch( elementsStore ).add( 'Helium' );
114+
115+
// Expects the `getFilteredElements` to be bound separately and independently to the two registries
116+
expect( registry1.select( uiStore ).getFilteredElements() ).toEqual( [
117+
'Carbon',
118+
] );
119+
expect( registry2.select( uiStore ).getFilteredElements() ).toEqual( [
120+
'Helium',
121+
] );
122+
} );
123+
105124
it( 'can bind a memoized selector to a registry', () => {
106125
const registry = createRegistry();
107126
registry.register( elementsStore );

0 commit comments

Comments
 (0)