-
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
Editor: Added slug selector #4802
Conversation
Will this work together with #3418? We might have to use |
@atimmer Makes sense, refactored. |
…tPostEdits to be safer
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.
It still needs to be added here: https://github.com/WordPress/gutenberg/blob/master/editor/store/index.js#L29.
Otherwise, it looks good.
@@ -200,7 +211,7 @@ export function getCurrentPostLastRevisionId( state ) { | |||
* @returns {Object} Object of key value pairs comprising unsaved edits. | |||
*/ | |||
export function getPostEdits( state ) { | |||
return state.editor.present.edits; | |||
return get( state, [ 'editor', 'present', 'edits' ], {} ); |
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.
Just noting that you can use also string as 2nd param:
return get( state, 'editor.present.edits', {} );
See 3rd example in here
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.
@gziolo I know, this is a small performance consideration because lodash won't have to parse the string.
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.
Hehe, more keystrokes to save some CPU time. They should include lodash
into JS engine by default and optimize that for us or teach Babel to do the transformation from string to array!
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.
Just noting that you can use also string as 2nd param:
We seem to be encouraging the opposite thing, as I tend to leave the inverse as a suggestion whenever possible 😉 Beside the performance advantage, I find it trivially more legible by virtue of greater separation between the properties.
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.
Aside: Why would state.editor.present.edits
ever be undefined?
(I hope the answer is not "because tests")
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.
Further, if this triggers the default, since it's not a shared reference, two subsequent invocations of this function would not be strictly equal and therefore trigger re-renders on any connect
ed components relying on the result of this function:
const state = {};
getPostEdits( state ) !== getPostEdits( state );
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.
That's a good catch about having {}
as the default value. The same would apply to []
.
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.
One example where I worked around this was in getBlockOrder
:
gutenberg/editor/store/selectors.js
Lines 33 to 40 in e2c824a
/** | |
* Shared reference to an empty array used as the default block order return | |
* value when the state value is not explicitly assigned, since we want to | |
* avoid returning a new array reference on every invocation. | |
* | |
* @type {Array} | |
*/ | |
const DEFAULT_BLOCK_ORDER = []; |
gutenberg/editor/store/selectors.js
Lines 788 to 801 in e2c824a
/** | |
* Returns an array containing all block unique IDs of the post being edited, | |
* in the order they appear in the post. Optionally accepts a root UID of the | |
* block list for which the order should be returned, defaulting to the top- | |
* level block order. | |
* | |
* @param {Object} state Global application state. | |
* @param {?string} rootUID Optional root UID of block list. | |
* | |
* @return {Array} Ordered unique IDs of post blocks. | |
*/ | |
export function getBlockOrder( state, rootUID ) { | |
return state.editor.present.blockOrder[ rootUID || '' ] || DEFAULT_BLOCK_ORDER; | |
} |
I'd not love if we start having many constants at the top of this file, but we also should try to avoid these fallbacks whenever possible (instead relying on the value reference living in state as the result of the reducer).
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.
There could be 2 constants, one for an empty array and one for an empty object. However I second your opinion that reducers should handle it.
@@ -214,9 +225,10 @@ export function getPostEdits( state ) { | |||
* @returns {*} Post attribute value. | |||
*/ | |||
export function getEditedPostAttribute( state, attributeName ) { | |||
return state.editor.present.edits[ attributeName ] === undefined ? | |||
const edits = getPostEdits( state ); |
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.
Nice 👍
editor/store/test/selectors.js
Outdated
@@ -375,6 +376,31 @@ describe( 'selectors', () => { | |||
} ); | |||
} ); | |||
|
|||
describe( 'getCurrentPostSlug', () => { | |||
it( 'should return the current post\'s slug is no edits have been made', () => { |
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.
typo: slug *is* no edits
-> slug if no edits
Looks good, nice work on this one. I would wait for @youknowriad to perform a final check. I'm still learning how this should be exposed to make it scalable. We might want also to document all exposed selectors in our docs. |
👍 LGTM Also @aduth proposed that we expose all our selectors (which forces us to ensure backwards compatibilty but maybe it's fine) |
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.
Why do we need a dedicated selector for slug, when getEditedPostAttribute
should work just as well?
I'd like to avoid excessive proliferation of selectors, since as implemented with these changes, there's no reason we shouldn't have selectors for the 23 other properties of the edited post (I'm arguing this as a bad thing).
@@ -200,7 +211,7 @@ export function getCurrentPostLastRevisionId( state ) { | |||
* @returns {Object} Object of key value pairs comprising unsaved edits. | |||
*/ | |||
export function getPostEdits( state ) { | |||
return state.editor.present.edits; | |||
return get( state, [ 'editor', 'present', 'edits' ], {} ); |
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.
Just noting that you can use also string as 2nd param:
We seem to be encouraging the opposite thing, as I tend to leave the inverse as a suggestion whenever possible 😉 Beside the performance advantage, I find it trivially more legible by virtue of greater separation between the properties.
@@ -200,7 +211,7 @@ export function getCurrentPostLastRevisionId( state ) { | |||
* @returns {Object} Object of key value pairs comprising unsaved edits. | |||
*/ | |||
export function getPostEdits( state ) { | |||
return state.editor.present.edits; | |||
return get( state, [ 'editor', 'present', 'edits' ], {} ); |
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.
Aside: Why would state.editor.present.edits
ever be undefined?
(I hope the answer is not "because tests")
@@ -200,7 +211,7 @@ export function getCurrentPostLastRevisionId( state ) { | |||
* @returns {Object} Object of key value pairs comprising unsaved edits. | |||
*/ | |||
export function getPostEdits( state ) { | |||
return state.editor.present.edits; | |||
return get( state, [ 'editor', 'present', 'edits' ], {} ); |
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.
Further, if this triggers the default, since it's not a shared reference, two subsequent invocations of this function would not be strictly equal and therefore trigger re-renders on any connect
ed components relying on the result of this function:
const state = {};
getPostEdits( state ) !== getPostEdits( state );
@aduth I'm starting work on addressing your concerns. |
Description
Adds selector for slug.
How Has This Been Tested?
Added unit tests.
Ran
wp.data.select( "core/editor", "getCurrentPostSlug" );
in the console.Types of changes
Addition to the selector API.
Checklist: