-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Blocks: Add a data store to manage the block/categories registration #6679
Changes from all commits
d1981c2
e55bfb2
4a6ef5a
f8cc10f
e8ef768
ff24c10
2a522d4
9606965
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,13 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
/** | ||
* Block categories are defined groups for organizing blocks. | ||
* | ||
* @var {Array} categories | ||
*/ | ||
const categories = [ | ||
{ slug: 'common', title: __( 'Common Blocks' ) }, | ||
{ slug: 'formatting', title: __( 'Formatting' ) }, | ||
{ slug: 'layout', title: __( 'Layout Elements' ) }, | ||
{ slug: 'widgets', title: __( 'Widgets' ) }, | ||
{ slug: 'embed', title: __( 'Embeds' ) }, | ||
{ slug: 'shared', title: __( 'Shared Blocks' ) }, | ||
]; | ||
import { select } from '@wordpress/data'; | ||
|
||
/** | ||
* Returns all the block categories. | ||
* | ||
* @return {Array} Block categories. | ||
*/ | ||
export function getCategories() { | ||
return categories; | ||
return select( 'core/blocks' ).getCategories(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { castArray } from 'lodash'; | ||
|
||
/** | ||
* Returns an action object used in signalling that block types have been added. | ||
* | ||
* @param {Array|Object} blockTypes Block types received. | ||
* | ||
* @return {Object} Action object. | ||
*/ | ||
export function addBlockTypes( blockTypes ) { | ||
return { | ||
type: 'ADD_BLOCK_TYPES', | ||
blockTypes: castArray( blockTypes ), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the fact that this action receives multiple blocks. It opens the door to bulk registration, instead of dispatching one action per register block. But, right now we call registerBlockType per block so an action is dispatched per block and at the start, we are dispatching many actions. Right after landing this, I think we should change our registration mechanism to make use of the possibility of using ADD_BLOCK_TYPES with multiple blocks. If a general approach does not look feasible at least, we can change our registerCoreBlocks to register all core blocks with a single action. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that sounds like a good enhancement. I didn't want to change the Public API yet because the work that needs to be done on the server-side awareness of blocks will inevitably change the API, so it's better to deprecate things once. |
||
}; | ||
} | ||
|
||
/** | ||
* Returns an action object used to remove a registered block type. | ||
* | ||
* @param {string|Array} names Block name. | ||
* | ||
* @return {Object} Action object. | ||
*/ | ||
export function removeBlockTypes( names ) { | ||
return { | ||
type: 'REMOVE_BLOCK_TYPES', | ||
names: castArray( names ), | ||
}; | ||
} | ||
|
||
/** | ||
* Returns an action object used to set the default block name. | ||
* | ||
* @param {string} name Block name. | ||
* | ||
* @return {Object} Action object. | ||
*/ | ||
export function setDefaultBlockName( name ) { | ||
return { | ||
type: 'SET_DEFAULT_BLOCK_NAME', | ||
name, | ||
}; | ||
} | ||
|
||
/** | ||
* Returns an action object used to set the fallback block name. | ||
* | ||
* @param {string} name Block name. | ||
* | ||
* @return {Object} Action object. | ||
*/ | ||
export function setFallbackBlockName( name ) { | ||
return { | ||
type: 'SET_FALLBACK_BLOCK_NAME', | ||
name, | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { registerStore } from '@wordpress/data'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import reducer from './reducer'; | ||
import * as selectors from './selectors'; | ||
import * as actions from './actions'; | ||
|
||
registerStore( 'core/blocks', { reducer, selectors, actions } ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getBlockTypes is used for example to get the transforms. So it seems we are saving function references in the state. Maybe we can just save the serializable block information in the state (title icon etc...), and have an external object that maps the block to the non-serializable information like functions in the transforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can make use of resolvers or something similar, so it looks like everything is in the store, and we can select and dispatch as we do now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally think it's ok to save non-serializable data in the state. The benefits outgrow the downsides. Having serializable information in state is only needed if you want to persist state or dispatch things over the network. I think the blocks store is not something we'd want to persist or dispatch over the network if we implement collaborative editing for instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree saving the function references in state simplifies the things. Most sources discourage saving non-serializable info state, but objectively it looks like the only thing we lose is the ability to persist and rehydrate data https://github.com/markerikson/redux/blob/create-faq-page/docs/FAQ.md#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state, so I'm ok with doing this tradeoff as I did not found other concrete disavantages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy so long as it doesn't break the very useful time travelling feature in Redux DevTools. I just tested it then and it seems OK 🙂