-
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
Lodash: Remove _.get()
from various blocks
#48491
Conversation
Size Change: +142 B (0%) Total Size: 1.34 MB
ℹ️ View Unchanged
|
@@ -247,8 +246,8 @@ function Placeholder( { clientId, name, setAttributes } ) { | |||
return ( | |||
<div { ...blockProps }> | |||
<__experimentalBlockVariationPicker | |||
icon={ get( blockType, [ 'icon', 'src' ] ) } | |||
label={ get( blockType, [ 'title' ] ) } | |||
icon={ blockType?.icon?.src } |
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.
blockType
could be undefined
:
return state.blockTypes[ name ]; |
@@ -57,7 +56,7 @@ const USERS_LIST_QUERY = { | |||
}; | |||
|
|||
function getFeaturedImageDetails( post, size ) { | |||
const image = get( post, [ '_embedded', 'wp:featuredmedia', '0' ] ); | |||
const image = post._embedded?.[ 'wp:featuredmedia' ]?.[ '0' ]; |
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.
post
is certainly defined an an object, and used as one earlier:
let excerpt = post.excerpt.rendered; |
The rest may not exist, so we're adding optional chaining.
0 | ||
), | ||
defaultImageWidth: | ||
settings.imageDimensions?.[ featuredImageSizeSlug ] |
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.
settings
will always be an object:
export const SETTINGS_DEFAULTS = { |
but since it can be modified, we can't be certain that imageDimensions
will exist. As a matter of fact, it doesn't exist in the default settings. So we're adding optional chaining for the rest of the chain, and nullish coalescing for the default value.
[] | ||
); | ||
const colors = | ||
select( blockEditorStore ).getSettings().colors ?? []; |
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.
Same as above, getSettings()
will always return an object, but colors may not exists, in which case we'll default to the empty array.
const getValueFromObjectPath = ( object, path ) => { | ||
const normalizedPath = path.split( '.' ); | ||
let value = object; | ||
normalizedPath.forEach( ( fieldName ) => { | ||
value = value?.[ fieldName ]; | ||
} ); | ||
return value; | ||
}; |
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.
We're introducing a simple helper here to separate the concerns. It's as simple as possible: supporting only a string path, separated by dots (which was the original behavior).
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 wondering if we could use such a helper in other places, too? It seems worth to follow up and/or add a note so we don't forget about it. I know it's just a tiny little helper function but tests may be worthwhile (leaving that to you).
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 don't think it's worth the effort and packaging, to be honest. Also, one of the benefits of Lodash has been decoupling and IMHO such a simple helper won't bring many benefits for the added cost of additional dependencies and additional coupling a utility package might bring over time.
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 would love for this to be tested. It seems there aren't a lot of tests for anything in this file though.
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.
Happy to add some tests in a follow-up PR. Will ping you for taking a look.
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.
See #48956
columnCount === undefined | ||
? get( firstRow, [ 'cells', 'length' ] ) | ||
: columnCount; | ||
columnCount === undefined ? firstRow?.cells?.length : columnCount; |
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.
Theoretically, firstRow
could be undefined
, thus the optional chaining.
{} | ||
); | ||
const firstCellInColumn = | ||
firstRow?.cells?.[ index ] ?? {}; |
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.
Theoretically, firstRow
could be undefined
, thus the optional chaining.
@@ -310,7 +301,7 @@ export function toggleSection( state, sectionName ) { | |||
} | |||
|
|||
// Get the length of the first row of the body to use when creating the header. | |||
const columnCount = get( state, [ 'body', 0, 'cells', 'length' ], 1 ); | |||
const columnCount = state.body?.[ 0 ]?.cells?.length ?? 1; |
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.
body
should always exist as per my manual checks, but I prefer not taking chances.
@@ -64,7 +59,7 @@ export default function TextColumnsEdit( { attributes, setAttributes } ) { | |||
> | |||
<RichText | |||
tagName="p" | |||
value={ get( content, [ index, 'children' ] ) } | |||
value={ content?.[ index ]?.children } |
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.
We're being flexible here since the content
comes from an outside attribute and could potentially not exist.
@@ -20,7 +15,7 @@ export default function save( { attributes } ) { | |||
<div className="wp-block-column" key={ `column-${ index }` }> | |||
<RichText.Content | |||
tagName="p" | |||
value={ get( content, [ index, 'children' ] ) } | |||
value={ content?.[ index ]?.children } |
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.
We're being flexible here since the content
comes from an outside attribute and could potentially not exist.
Flaky tests detected in 57e1add. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4373592325
|
'large', | ||
'source_url', | ||
] ); | ||
media?.sizes?.large?.url || |
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.
Seems like media
should be defined. Shall we remove the first ?
?
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.
Good call 👍
Removed in dc1ab15. ✅
I also removed the second one, since this is wrapped in an if()
that ensures that media.sizes
will also be defined.
const getValueFromObjectPath = ( object, path ) => { | ||
const normalizedPath = path.split( '.' ); | ||
let value = object; | ||
normalizedPath.forEach( ( fieldName ) => { | ||
value = value?.[ fieldName ]; | ||
} ); | ||
return value; | ||
}; |
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 wondering if we could use such a helper in other places, too? It seems worth to follow up and/or add a note so we don't forget about it. I know it's just a tiny little helper function but tests may be worthwhile (leaving that to you).
@flootr I'd appreciate another review of this PR when you get a chance. |
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.
LGTM. I went through everything mentioned in the testing instructions and it appears to work fine 👍🏻
const getValueFromObjectPath = ( object, path ) => { | ||
const normalizedPath = path.split( '.' ); | ||
let value = object; | ||
normalizedPath.forEach( ( fieldName ) => { | ||
value = value?.[ fieldName ]; | ||
} ); | ||
return value; | ||
}; |
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 would love for this to be tested. It seems there aren't a lot of tests for anything in this file though.
dc1ab15
to
57e1add
Compare
What?
This PR removes Lodash's
_.get()
from various blocks that are using it.Why?
Lodash is known to unnecessarily inflate the bundle size of packages, and in most cases, it can be replaced with native language functionality. See these for more information and rationale:
@wordpress/api-fetch
package haslodash
as a dependency #39495How?
We're using optional chaining and nullish coalescing instead.
Testing Instructions
large
orfull
size.mainColor
attribute still properly displays the border colors.