-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Fix resolver resolution status key types mismatch causing unwanted resolver calls for identical state data #52120
Conversation
Size Change: +144 B (0%) Total Size: 1.65 MB
ℹ️ View Unchanged
|
This comment was marked as resolved.
This comment was marked as resolved.
842b6f3
to
8462ae4
Compare
Can I ask why do we want to consider "1" and 1 as equivalent in the first place? Is it certain that we want to do this or is this a bug elsewhere (where we lose the actual type of the identifier) |
We only want to do this in the case where {
title: "My Post",
id: 123,
type: 'some_post_type'
} ...these two calls are asking for the same data: // String as Post ID as record key
getEntityRecord('postType', 'some_post_type', '123');
// Number as Post ID as record key
getEntityRecord('postType', 'some_post_type', 123); If we don't do this then the cache will think it's empty and the resolver will be triggered even though it's already been resolved for the given
No I don't believe it's a bug "with type "loss". The type is passed to the selector/resolver when it is called incorrectly with a The caller is wrong and the resolver is just doing what it should do. We can protect the caller from this bug. It is being "clever" so there's an argument to just leave it "as is", but that results in additional network requests as I hope I've explained in the Issue and this PR. Alternatives consideredOne other option might be to introduce a new selector/resolver specifically for fetching records by Post ID. Something like Reasons I don't favour that:
More ContextThe issue that for // String as Post ID as record key
getEntityRecord('postType', 'some_post_type', '123');
// Number as Post ID as record key
getEntityRecord('postType', 'some_post_type', 123); There are no guards in place and nor can we add any because there are cases when // Slug as recordKey
getEntityRecords('postType', 'wp_template_part', 'twentytwentythree//header'); This flexibility is great except that it allows those who are intending to pass a post ID as Now we could say "everyone should know to pass We could of course patch the individual instances within the Gutenberg repo where As far as I can see there isn't a cleaner solution to this problem but I'm open to discussion. |
I mean if third parties are doing it wrong, it's also their problem. I'm "ok" with this normalization but can't stop but wonder whether it's really necessary. Is there a lot of places where we use "strings" instead of "numbers" in Gutenberg? |
It might be that calling selectors with "wrong" argument types is a very common mistake, it just goes undetected. Because the consequences are not that bad, it's just that the potential resolver is called twice. If your state is stored as an object, then It seems to me that mixing up |
I'll proceed then 🙇♂️ |
I'm now stuck with TypeScript in allowing the |
…matching resolver
As per code review
fb67d28
to
5d2c7b3
Compare
What?
Stops unwanted resolver calls due to resolver cache misses.
Specifically fixes
getEntityRecord
in@wordpress/core-data
to avoid cache miss caused by type mismatch on therecordKey
argument.Closes #52106
Why?
The following selector calls are not considered equivalent by the caching mechanism in
@wordpress/data
(see #52106 for detailed explanation):This means that even if the record exists in state, the relevant resolver is not marked as resolved and thus the resolver runs again thereby triggering a network request.
This is very likely to occur because in Gutenberg
ID
s can be strings which means a lot of (potential) cache misses and unnecessary network calls and loading delays.A specific example is the
useNavigator
hooks where the resultingparams
object will contain params as strings even if they are numeric. So if there's a param ofpostId
then it will be a string. It's very easy to accidentally pass that togetEntityRecord
.How?
Adds a new optional property to the
resolverselector which allows the implementor to define a method which normalizes theresolverargs
passed to the selector into to a standard form. This standardised form is then used in cache set/get.This PR implements such a method for the
getEntityRecord
resolverselector to stabize the type of therecordKey
as a number rather than a string when therecordKey
argument looks like a numberic ID (which is likely to be the ID of a Post record).Testing Instructions
Esc
to also open theConsole
tab below it.wp.data.select('core').getEntityRecords('postType', 'wp_navigation')
. You should seenull
and then running it again you should see results. This has populated thecore/data
state with entities of that type.id
s of those records.getEntityRecords
resolves thegetEntityRecord
selectors.wp.data.select('core').getEntityRecord('postType', 'wp_navigation','{YOUR_RECORD_ID}')
GET
request (ignoreOPTIONS
) towp/v2/navigation/{RECORD_ID}
.recordKey
argument aNumber
....you can also test this in the Site Editor by:
Navigation
in Browse Mode sidebar.GET
network request was dispatched.Testing Instructions for Keyboard
Screenshots or screencast