Skip to content

Commit

Permalink
Data: remove usage of deprecated register methods (#36344)
Browse files Browse the repository at this point in the history
* Remove defunct unit test for dispatch-during-resolve

* core/data store: export store descriptor from the module

* useSelect test: register and use a test store the new way

* Rewrite generic registration examples in README

* Data: use registerGenericStore only for its own tests

* Use deprecated() in registerGenericStore
  • Loading branch information
jsnajdr committed Nov 19, 2021
1 parent 0000f96 commit 319deee
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 213 deletions.
102 changes: 51 additions & 51 deletions packages/data/README.md
Expand Up @@ -164,83 +164,83 @@ Integrating an existing redux store with its own reducers, store enhancers and m
_Example:_

```js
import { mapValues } from 'lodash';
import { register } from '@wordpress/data';
import existingSelectors from './existing-app/selectors';
import existingActions from './existing-app/actions';
import createStore from './existing-app/store';

import { registerGenericStore } from 'wordpress/data';

const reduxStore = createStore();

const mappedSelectors = Object.keys( existingSelectors ).reduce(
( acc, selectorKey ) => {
acc[ selectorKey ] = ( ...args ) =>
existingSelectors[ selectorKey ]( reduxStore.getState(), ...args );
return acc;
},
{}
const boundSelectors = mapValues(
existingSelectors,
( selector ) => ( ...args ) => selector( reduxStore.getState(), ...args )
);

const mappedActions = Object.keys( existingActions ).reduce(
( acc, actionKey ) => {
acc[ actionKey ] = ( ...args ) =>
reduxStore.dispatch( existingActions[ actionKey ]( ...args ) );
return acc;
},
{}
const boundActions = mapValues( existingActions, ( action ) => ( ...args ) =>
reduxStore.dispatch( action( ...args ) )
);

const genericStore = {
getSelectors() {
return mappedSelectors;
},
getActions() {
return mappedActions;
},
subscribe: reduxStore.subscribe,
name: 'existing-app',
instantiate: () => ( {
getSelectors: () => boundSelectors,
getActions: () => boundActions,
subscribe: reduxStore.subscribe,
} ),
};

registerGenericStore( 'existing-app', genericStore );
register( genericStore );
```

It is also possible to implement a completely custom store from scratch:

_Example:_

```js
import { registerGenericStore } from '@wordpress/data';

function createCustomStore() {
let storeChanged = () => {};
const prices = { hammer: 7.5 };

const selectors = {
getPrice( itemName ) {
return prices[ itemName ];
},
};

const actions = {
setPrice( itemName, price ) {
prices[ itemName ] = price;
storeChanged();
},
};
import { register } from '@wordpress/data';

function customStore() {
return {
getSelectors() {
return selectors;
},
getActions() {
return actions;
},
subscribe( listener ) {
storeChanged = listener;
name: 'custom-data',
instantiate: () => {
const listeners = new Set();
const prices = { hammer: 7.5 };

function storeChanged() {
for ( const listener of listeners ) {
listener();
}
}

function subscribe( listener ) {
listeners.add( listener );
return () => listeners.delete( listener );
}

const selectors = {
getPrice( itemName ) {
return prices[ itemName ];
},
};

const actions = {
setPrice( itemName, price ) {
prices[ itemName ] = price;
storeChanged();
},
};

return {
getSelectors: () => selectors,
getActions: () => actions,
subscribe,
};
},
};
}

registerGenericStore( 'custom-data', createCustomStore() );
register( customStore );
```

## Comparison with Redux
Expand Down
64 changes: 32 additions & 32 deletions packages/data/src/components/use-select/test/index.js
Expand Up @@ -723,42 +723,42 @@ describe( 'useSelect', () => {
it( 'handles custom generic stores without a unsubscribe function', () => {
let renderer;

function createCustomStore() {
let storeChanged = () => {};
let counter = 0;

const selectors = {
getCounter: () => counter,
};

const actions = {
increment: () => {
counter += 1;
storeChanged();
},
};
const customStore = {
name: 'generic-store',
instantiate() {
let storeChanged = () => {};
let counter = 0;

const selectors = {
getCounter: () => counter,
};

const actions = {
increment: () => {
counter += 1;
storeChanged();
},
};

return {
getSelectors() {
return selectors;
},
getActions() {
return actions;
},
subscribe( listener ) {
storeChanged = listener;
},
};
}
return {
getSelectors() {
return selectors;
},
getActions() {
return actions;
},
subscribe( listener ) {
storeChanged = listener;
},
};
},
};

registry.registerGenericStore(
'generic-store',
createCustomStore()
);
registry.register( customStore );

const TestComponent = jest.fn( () => {
const state = useSelect(
( select ) => select( 'generic-store' ).getCounter(),
( select ) => select( customStore ).getCounter(),
[]
);

Expand All @@ -778,7 +778,7 @@ describe( 'useSelect', () => {
expect( testInstance.findByType( 'div' ).props.data ).toBe( 0 );

act( () => {
registry.dispatch( 'generic-store' ).increment();
registry.dispatch( customStore ).increment();
} );

expect( testInstance.findByType( 'div' ).props.data ).toBe( 1 );
Expand Down
73 changes: 43 additions & 30 deletions packages/data/src/registry.js
Expand Up @@ -3,12 +3,16 @@
*/
import { mapValues, isObject, forEach } from 'lodash';

/**
* WordPress dependencies
*/
import deprecated from '@wordpress/deprecated';

/**
* Internal dependencies
*/
import createReduxStore from './redux-store';
import createCoreDataStore from './store';
import { STORE_NAME } from './store/name';
import coreDataStore from './store';
import { createEmitter } from './utils/emitter';

/** @typedef {import('./types').WPDataStore} WPDataStore */
Expand Down Expand Up @@ -159,12 +163,12 @@ export function createRegistry( storeConfigs = {}, parent = null ) {
}

/**
* Registers a generic store.
* Registers a store instance.
*
* @param {string} name Store registry name.
* @param {Object} store Store instance object (getSelectors, getActions, subscribe).
*/
function registerGenericStore( name, store ) {
function registerStoreInstance( name, store ) {
if ( typeof store.getSelectors !== 'function' ) {
throw new TypeError( 'store.getSelectors must be a function' );
}
Expand Down Expand Up @@ -204,7 +208,35 @@ export function createRegistry( storeConfigs = {}, parent = null ) {
* @param {WPDataStore} store Store definition.
*/
function register( store ) {
registerGenericStore( store.name, store.instantiate( registry ) );
registerStoreInstance( store.name, store.instantiate( registry ) );
}

function registerGenericStore( name, store ) {
deprecated( 'wp.data.registerGenericStore', {
since: '5.9',
alternative: 'wp.data.register( storeDescriptor )',
} );
registerStoreInstance( name, store );
}

/**
* Registers a standard `@wordpress/data` store.
*
* @param {string} storeName Unique namespace identifier.
* @param {Object} options Store description (reducer, actions, selectors, resolvers).
*
* @return {Object} Registered store object.
*/
function registerStore( storeName, options ) {
if ( ! options.reducer ) {
throw new TypeError( 'Must specify store reducer' );
}

const store = createReduxStore( storeName, options ).instantiate(
registry
);
registerStoreInstance( storeName, store );
return store.store;
}

/**
Expand Down Expand Up @@ -240,7 +272,6 @@ export function createRegistry( storeConfigs = {}, parent = null ) {

let registry = {
batch,
registerGenericStore,
stores,
namespaces: stores, // TODO: Deprecate/remove this.
subscribe,
Expand All @@ -249,30 +280,12 @@ export function createRegistry( storeConfigs = {}, parent = null ) {
dispatch,
use,
register,
registerGenericStore,
registerStore,
__experimentalMarkListeningStores,
__experimentalSubscribeStore,
};

/**
* Registers a standard `@wordpress/data` store.
*
* @param {string} storeName Unique namespace identifier.
* @param {Object} options Store description (reducer, actions, selectors, resolvers).
*
* @return {Object} Registered store object.
*/
registry.registerStore = ( storeName, options ) => {
if ( ! options.reducer ) {
throw new TypeError( 'Must specify store reducer' );
}

const store = createReduxStore( storeName, options ).instantiate(
registry
);
registerGenericStore( storeName, store );
return store.store;
};

//
// TODO:
// This function will be deprecated as soon as it is no longer internally referenced.
Expand All @@ -286,11 +299,11 @@ export function createRegistry( storeConfigs = {}, parent = null ) {
return registry;
}

registerGenericStore( STORE_NAME, createCoreDataStore( registry ) );
registry.register( coreDataStore );

Object.entries( storeConfigs ).forEach( ( [ name, config ] ) =>
registry.registerStore( name, config )
);
for ( const [ name, config ] of Object.entries( storeConfigs ) ) {
registry.register( createReduxStore( name, config ) );
}

if ( parent ) {
parent.subscribe( globalListener );
Expand Down
6 changes: 3 additions & 3 deletions packages/data/src/resolvers-cache-middleware.js
Expand Up @@ -6,7 +6,7 @@ import { get } from 'lodash';
/**
* Internal dependencies
*/
import { STORE_NAME } from './store/name';
import coreDataStore from './store';

/** @typedef {import('./registry').WPDataRegistry} WPDataRegistry */

Expand All @@ -24,7 +24,7 @@ const createResolversCacheMiddleware = ( registry, reducerKey ) => () => (
next
) => ( action ) => {
const resolvers = registry
.select( STORE_NAME )
.select( coreDataStore )
.getCachedResolvers( reducerKey );
Object.entries( resolvers ).forEach(
( [ selectorName, resolversByArgs ] ) => {
Expand All @@ -49,7 +49,7 @@ const createResolversCacheMiddleware = ( registry, reducerKey ) => () => (

// Trigger cache invalidation
registry
.dispatch( STORE_NAME )
.dispatch( coreDataStore )
.invalidateResolution( reducerKey, selectorName, args );
} );
}
Expand Down

0 comments on commit 319deee

Please sign in to comment.