Skip to content

Commit

Permalink
State: Use more general-purpose wp.data plugins.
Browse files Browse the repository at this point in the history
This creates a `custom-store-plugin` which is more general-purpose than
the previous `calypso-registry-plugin`. It allows any pre-existing redux
store to be used for a given wp.data store instead of wp.data creating
one itself. This allows for two things:

1. Stores can use enhancers and middleware, which is not possible in the
default wp.data configuration.
2. wp.data stores can share redux stores.

Note: This also creates an `internals-plugin`, which is necessary to
avoid the reimplementing of internals within the
`calypso-registry-plugin`. The `use` function of the `internals-plugin`
will be submitted as a PR to core Gutenberg as well so perhaps it will
not be necessary for long.
  • Loading branch information
coderkevin committed Sep 6, 2018
1 parent 17b8bda commit d7324b4
Show file tree
Hide file tree
Showing 7 changed files with 590 additions and 130 deletions.
115 changes: 0 additions & 115 deletions client/state/wp-data/calypso-registry-plugin.js

This file was deleted.

4 changes: 2 additions & 2 deletions client/state/wp-data/calypso-stores/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
*/
import preferences from './preferences';

export default {
'calypso/preferences': preferences,
export function registerStores( registry, calypsoStore ) {
registry.registerStore( 'calypso/preferences', preferences, calypsoStore );
};
1 change: 0 additions & 1 deletion client/state/wp-data/calypso-stores/preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { fetchPreferences, setPreference, savePreference } from 'state/preferenc
import { getPreference, isFetchingPreferences } from 'state/preferences/selectors';

export default {
useCalypsoStore: true,
selectors: {
getPreference,
isFetchingPreferences,
Expand Down
21 changes: 9 additions & 12 deletions client/state/wp-data/calypso-wp-data-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,14 @@
* External dependencies
*/
import React, { Component } from 'react';
import { use, RegistryProvider } from '@wordpress/data';
import { createRegistry, RegistryProvider } from '@wordpress/data';

/**
* Internal dependencies
*/
import calypsoRegistryPlugin from './calypso-registry-plugin';
import calypsoStores from './calypso-stores';

function registerStores( registry, stores ) {
Object.keys( stores ).forEach( key => {
const store = stores[ key ];
registry.registerStore( key, store );
} );
}
import internalsPlugin from './plugins/internals-plugin';
import customStorePlugin from './plugins/custom-store-plugin';
import { registerStores } from './calypso-stores';

class CalypsoWPDataProvider extends Component {
constructor( props ) {
Expand All @@ -25,8 +19,11 @@ class CalypsoWPDataProvider extends Component {
}

updateRegistry( calypsoStore ) {
this.registry = use( calypsoRegistryPlugin( calypsoStore ) );
registerStores( this.registry, calypsoStores );
this.registry = createRegistry()
.use( internalsPlugin )
.use( customStorePlugin );

registerStores( this.registry, calypsoStore );
}

componentDidUpdate( prevProps ) {
Expand Down
81 changes: 81 additions & 0 deletions client/state/wp-data/plugins/custom-store-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/** @format */

/**
* Creates a plugin that allows custom store implementations.
*
* IMPORTANT: This plugin depends on the `internals-plugin` to work.
* It must be given a registry already using that plugin.
*
* @param {Object} registry The original registry to wrap.
* @return {Object} The wrapped registry from this plugin.
*/
function customStorePlugin( registry ) {
if ( ! registry._internals ) {
throw TypeError( 'Expected a registry with _internals. See internals-plugin' );
}

/**
* Registers a custom store with actions and selectors.
*
* @param {string} reducerKey Reducer key.
* @param {Object} store Existing redux-like store to be used.
* @return {Object} Store originally given, now registered.
*/
function registerCustomStore( reducerKey, store ) {
const { globalListener, namespaces } = registry._internals;

namespaces[ reducerKey ] = { store };

// Customize subscribe behavior to call listeners only on effective change,
// not on every dispatch.
let lastState = store.getState();
store.subscribe( () => {
const state = store.getState();
const hasChanged = state !== lastState;
lastState = state;

if ( hasChanged ) {
globalListener();
}
} );

return store;
}

/**
* Registers a store within the registry.
*
* @param {String} reducerKey The desired key to denote this store.
* @param {Object} options Options for store, such as actions, selectors.
* @param {Object} [customStore] Optional custom store to use instead of creating one.
* @return {Object} The newly registered store.
*/
function registerStore( reducerKey, options, customStore ) {
if ( customStore ) {
const store = registerCustomStore( reducerKey, customStore );

if ( options.actions ) {
registry.registerActions( reducerKey, options.actions );
}

if ( options.selectors ) {
registry.registerSelectors( reducerKey, options.selectors );
}

if ( options.resolvers ) {
registry.registerResolvers( reducerKey, options.resolvers );
}

return store;
}

// No store given in options, pass through to normal operation.
return registry.registerStore( reducerKey, options );
}

return {
registerStore,
};
}

export default customStorePlugin;
Loading

0 comments on commit d7324b4

Please sign in to comment.