Skip to content
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

Edit Site: Fix useEditedEntityRecord() loading state #50730

Merged
merged 3 commits into from
May 18, 2023
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export default function useEditedEntityRecord( postType, postId ) {
( select ) => {
const { getEditedPostType, getEditedPostId } =
select( editSiteStore );
const { getEditedEntityRecord } = select( coreStore );
const { getEditedEntityRecord, hasFinishedResolution } =
select( coreStore );
const { __experimentalGetTemplateInfo: getTemplateInfo } =
select( editorStore );
const usedPostType = postType ?? getEditedPostType();
Expand All @@ -26,7 +27,11 @@ export default function useEditedEntityRecord( postType, postId ) {
usedPostType,
usedPostId
);
const _isLoaded = !! usedPostId;
const _isLoaded = hasFinishedResolution( 'getEditedEntityRecord', [
'postType',
usedPostType,
usedPostId,
] );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably check if usedPostId is defined. Otherwise, you'll see the null flash in the title when visiting wp-admin/site-editor.php, because the editor is resolving the edited template from the server, and we get a false positive.

const _isLoaded =
				usedPostId &&
				hasFinishedResolution( 'getEditedEntityRecord', [
					'postType',
					usedPostType,
					usedPostId,
				] );

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, of course, good catch! Added in d032f4d

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why the extra usedPostId && ... check was needed here. If usedPostId is null, the hasFinishedSelector returns true for the null value?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say the idea is to not call the hasFinishedResolution selector at all if the post ID is null since we already know the result.

Copy link
Member

@Mamaduka Mamaduka May 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a point where both selectors use undefined as postId. The getEditedEntityRecord will resolve and return an empty object, and hasFinishedResolution will report that our template was loaded.

Example:

const { testRecord, testResolved } = useSelect( ( select ) => {
	const { getEditedEntityRecord, hasFinishedResolution } =
		select( coreStore );

	return {
		testRecord: getEditedEntityRecord(
			'postType',
			'wp_template',
			undefined
		),
		testResolved: hasFinishedResolution( 'getEditedEntityRecord', [
			'postType',
			'wp_template',
			undefined,
		] ),
	};
} );

console.log( { testRecord, testResolved } )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, now I see what's happening. A getEntityRecord( 'postType', 'wp_template', undefined ) call doesn't make sense. It will do a lookup like return items[ key ], but there is never a template with id === undefined, so it will always return undefined.

But it still calls the resolver, where undefined key does make sense. Instead of fetching a specific template from /templates/{key}, it will fetch all templates from /templates and store the list.

That's why we end up in a situation where getEntityRecord returns undefined (there's no item with undefined key) and hasFinishedResolution returns true (the list is loaded).

If usedPostId is not known, the hook shouldn't call any selector at all and return an empty-ish object right away.

const templateInfo = getTemplateInfo( _record );

return {
Expand Down