-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Fix warnings within useSelect of the bulk editing header #67872
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
base: trunk
Are you sure you want to change the base?
Changes from all commits
aec7269
2840862
5762893
6972c79
fce61de
e4cd460
9e4ceb6
ba6868a
9c55bef
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 |
|---|---|---|
|
|
@@ -21,27 +21,48 @@ import { usePostActions } from './actions'; | |
| const { Menu, kebabCase } = unlock( componentsPrivateApis ); | ||
|
|
||
| function useEditedEntityRecordsWithPermissions( postType, postIds ) { | ||
| const { items, permissions } = useSelect( | ||
| const { items, entityConfig } = useSelect( | ||
| ( select ) => { | ||
| const { getEditedEntityRecord, getEntityRecordPermissions } = | ||
| unlock( select( coreStore ) ); | ||
| const { getEntityConfig } = select( coreStore ); | ||
| const { getEditedEntityRecords } = unlock( select( coreStore ) ); | ||
| const entityRecords = getEditedEntityRecords( | ||
| 'postType', | ||
| postType, | ||
| postIds | ||
| ); | ||
|
|
||
| return { | ||
| items: postIds.map( ( postId ) => | ||
| getEditedEntityRecord( 'postType', postType, postId ) | ||
| ), | ||
| permissions: postIds.map( ( postId ) => | ||
| getEntityRecordPermissions( 'postType', postType, postId ) | ||
| ), | ||
| items: entityRecords, | ||
| entityConfig: getEntityConfig( 'postType', postType ), | ||
| }; | ||
| }, | ||
| [ postIds, postType ] | ||
| ); | ||
|
|
||
| const ids = useMemo( | ||
| () => | ||
| items?.map( ( record ) => record[ entityConfig?.key ?? 'id' ] ) ?? | ||
| [], | ||
| [ items, entityConfig?.key ] | ||
| ); | ||
|
|
||
| const permissions = useSelect( | ||
| ( select ) => { | ||
| const { getEntityRecordsPermissions } = unlock( | ||
| select( coreStore ) | ||
| ); | ||
| return getEntityRecordsPermissions( 'postType', postType, ids ); | ||
| }, | ||
| [ ids, postType ] | ||
| ); | ||
|
Comment on lines
+42
to
+57
Contributor
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. This is a bit of a drive-by comment, and I don't know much about the code, so I might be far off the mark. Can It seems inconsistent that it's possible to call
Contributor
Author
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.
It certainly could, I think we did have to create a separate selector to handle that.
Yeah, I can probably remove it now given I explicitly converted the |
||
|
|
||
| return useMemo( () => { | ||
| return items.map( ( item, index ) => ( { | ||
| ...item, | ||
| permissions: permissions[ index ], | ||
| } ) ); | ||
| return ( | ||
| items?.map( ( item, index ) => ( { | ||
| ...item, | ||
| permissions: permissions ? permissions[ index ] : undefined, | ||
| } ) ) ?? [] | ||
|
Comment on lines
+61
to
+64
Contributor
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. Again I'll leave a caveat that I don't know the code very well, but I feel a bit nervous about the way the permissions are merged into the entity records here. It might be better if this was TypeScript, but because it's JS, other contributors will have to trace back through the code to find out whether the items contain the permissions key or not. It's the kind of thing that could lead to bugs if another contributor makes a bad assumption. I think it's clearer and more intentional if they're kept separate, and also the hook ends up returning a more pure form of
Contributor
Author
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 don't know if I totally agree with this, given we explicitly set this list to the Having said that, I do agree that keeping them separate would be ideal. This would mean either updating the |
||
| ); | ||
| }, [ items, permissions ] ); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,52 +39,49 @@ export const TemplateEdit = ( { | |
| typeof data.id === 'number' ? data.id : parseInt( data.id, 10 ); | ||
| const slug = data.slug; | ||
|
|
||
| const { availableTemplates, templates } = useSelect( | ||
| const { templates, allowSwitchingTemplate } = useSelect( | ||
| ( select ) => { | ||
| const allTemplates = | ||
| select( coreStore ).getEntityRecords< WpTemplate >( | ||
| 'postType', | ||
| 'wp_template', | ||
| { | ||
| per_page: -1, | ||
| post_type: postType, | ||
| } | ||
| ) ?? []; | ||
| const allTemplates = select( | ||
| coreStore | ||
| ).getEntityRecords< WpTemplate >( 'postType', 'wp_template', { | ||
| per_page: -1, | ||
| post_type: postType, | ||
| } ); | ||
|
Contributor
Author
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. Remove the |
||
|
|
||
| const { getHomePage, getPostsPageId } = unlock( | ||
| select( coreStore ) | ||
| ); | ||
|
|
||
| const isPostsPage = getPostsPageId() === +postId; | ||
| const isPostsPage = getPostsPageId() === postId; | ||
| const isFrontPage = | ||
| postType === 'page' && getHomePage()?.postId === +postId; | ||
|
|
||
| const allowSwitchingTemplate = ! isPostsPage && ! isFrontPage; | ||
| postType === 'page' && getHomePage()?.postId === postId; | ||
|
|
||
| return { | ||
| templates: allTemplates, | ||
| availableTemplates: allowSwitchingTemplate | ||
| ? allTemplates.filter( | ||
| ( template ) => | ||
| template.is_custom && | ||
| template.slug !== data.template && | ||
| !! template.content.raw // Skip empty templates. | ||
| ) | ||
| : [], | ||
| allowSwitchingTemplate: ! isPostsPage && ! isFrontPage, | ||
| }; | ||
| }, | ||
| [ data.template, postId, postType ] | ||
| [ postId, postType ] | ||
| ); | ||
|
|
||
| const templatesAsPatterns = useMemo( | ||
| () => | ||
| availableTemplates.map( ( template ) => ( { | ||
| name: template.slug, | ||
| blocks: parse( template.content.raw ), | ||
| title: decodeEntities( template.title.rendered ), | ||
| id: template.id, | ||
| } ) ), | ||
| [ availableTemplates ] | ||
| allowSwitchingTemplate | ||
| ? ( templates ?? [] ) | ||
| .filter( | ||
| ( template ) => | ||
| template.is_custom && | ||
| template.slug !== data.template && | ||
| !! template.content.raw // Skip empty templates. | ||
| ) | ||
| .map( ( template ) => ( { | ||
| name: template.slug, | ||
| blocks: parse( template.content.raw ), | ||
| title: decodeEntities( template.title.rendered ), | ||
| id: template.id, | ||
| } ) ) | ||
| : [], | ||
| [ templates, allowSwitchingTemplate, data.template ] | ||
| ); | ||
|
|
||
| const shownTemplates = useAsyncList( templatesAsPatterns ); | ||
|
|
@@ -151,6 +148,10 @@ export const TemplateEdit = ( { | |
| variant="tertiary" | ||
| size="compact" | ||
| onClick={ onToggle } | ||
| accessibleWhenDisabled | ||
| disabled={ | ||
| value === '' && ! templatesAsPatterns.length | ||
| } | ||
| > | ||
| { currentTemplate | ||
| ? getItemTitle( currentTemplate ) | ||
|
|
@@ -159,14 +160,16 @@ export const TemplateEdit = ( { | |
| ) } | ||
| renderContent={ ( { onToggle } ) => ( | ||
| <MenuGroup> | ||
| <MenuItem | ||
| onClick={ () => { | ||
| setShowModal( true ); | ||
| onToggle(); | ||
| } } | ||
| > | ||
| { __( 'Swap template' ) } | ||
| </MenuItem> | ||
| { templatesAsPatterns.length > 0 && ( | ||
| <MenuItem | ||
| onClick={ () => { | ||
| setShowModal( true ); | ||
| onToggle(); | ||
| } } | ||
| > | ||
| { __( 'Swap template' ) } | ||
| </MenuItem> | ||
| ) } | ||
| { | ||
| // The default template in a post is indicated by an empty string | ||
| value !== '' && ( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.
At the start of
PostActions, there's auseMemocall (I can't leave a code comment there as it's not part of the changeset):I think that's unnecessary overhead, the coercion to an array can be performed in this
useSelectwithinuseEditedEntityRecordsWithPermissions. From what I could telluseEditedEntityRecordsWithPermissionsis the only place_postIdsis used, so I think it's a good idea to move that code inside this hook.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.
Yeah that is also an option, although if we move the
useMemocode into theuseSelectit would mean we pass a new array of ids intogetEditedEntityRecordswhich in turn will trigger the memoization of thegetEditedEntityRecordsselector and cause the same warning to appear that this PR attempts to prevent ( when handling single ids ).