-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Add private selector support to resolveSelect and suspendSelect #52036
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
Conversation
|
Size Change: -21 B (0%) Total Size: 1.85 MB
ℹ️ View Unchanged
|
75d8c79 to
df5bf85
Compare
|
Did this ever come up again? |
|
I think I merged some parts of it as separate, incremental PRs. I'll need to have a closer look at what is the remaining work. |
f2251ef to
5968fd5
Compare
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
@ellatrix noticed the other day that unlock( registry.resolveSelect( myStore ) ).privateSelector(); // no `privateSelector` exposed
unlock( registry.select( myStore ) ).privateSelector(); // this worksHere I'm reviving an old PR of mine that adds the "private proxy" support to |
| selectorName, | ||
| selectorArgs, | ||
| ...args | ||
| ) => { |
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.
This is a slight refactor where selectorName and selectorArgs are directly referenced as selector arguments instead of accessing them as args[ 0 ] or args[ 1 ].
| hasResolvingSelectors, | ||
| countSelectorsByStatus, | ||
| ...storeSelectors | ||
| } = selectors; |
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.
Here we no longer need to exclude the metadata selectors because mapResolveSelector is no longer ever called with a metadata selector. We are more careful now about which kind of selector is mapped/bound with which mapping function.
It was very helpful to refactor functions that map all selectors at once:
function mapSelectors( selectors ) {
return mapValues( selectors, ( selector ) => { /* do the mapping */ } );
}to a function that maps just one selector at a time, allowing us to do the mapping more granularly and precisely:
function mapSelector( selector ) {
/* do the mapping */
}
const mappedSelectors = mapValues( selectors, mapSelector );6385593 to
6c81ea1
Compare
|
There are many e2e failures, mostly related to patterns. Something is probably broken. Working on it. |
This is now fully fixed, my changes accidentally broke |
| // 2. When the resolver check if it's already running. | ||
| // 3. When the resolver is fulfilled. | ||
| expect( normalizingFunction ).toHaveBeenCalledTimes( 3 ); |
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.
Is the extra call just a side-effect of refactoring that can't be avoided, or an actual bugfix?
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.
The multiple calls to normalize are a side-effect of how we're building functions that are both a public API exposed to users, and also a primitive used to build more complex functions. Examples:
- A
selectorfunction passed by store author inoptionsis "bound" to the store: afoo( state, ...args )function is wrapped in a function that binds thestateargument and normalizes theargs. This wrapped function is what is called by consumers inselect( store ).foo(). - If there is a
resolverspecified, the already "bound" selector from the previous step is further wrapped in another function that calls theresolveras a side effect. Theargsfor the resolver also need to be normalized. Then the "bound" selector is called withargsthat are already normalized. Thenormalizecall happens twice. - The metadata selectors like
hasFinishedResolution( selName, selArgs )are also exposed as public API, and therefore the "bound" version needs to normalizeselArgs. But at the same timehasFinishedResolutionis used internally to build theresolveSelectprimitive,hasStartedResolutionis called to check if we really need to callresolverwhen callingselector. That's a thirdnormalizecall.
I think it's possible to avoid the extra normalize calls with a careful refactoring, but I think it's a topic for a separate PR.
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.
Makes sense. Thanks for the detailed explanation!
Mamaduka
left a comment
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.
Thank you, @jsnajdr!
The code looks much cleaner after this refactoring, and I really appreciate the new inline comments 🙇
Haha, they are AI generated 😄 So often I start writing a sentence and Cursor guesses exactly what I wanted to write. |
…Press#52036) * Add private selector support to resolveSelect and suspendSelect * Add changelog entry * Always call bound metadata selector to ensure arg normalization * Fix number of normalizer calls in unit test
Adds support for resolvers to private selectors -- until now private selectors were never bound to the specified resolvers.
Also adds support for private selectors to
resolveSelectandsuspendSelect. Until now these function were returning only public selectors. Now they return locked objects that can be unlocked to access also private selectors.The patch is pretty big because is refactors all the logic for binding and proxying public and private actions and selectors. There's a new universal
createPrivateProxyhelper etc.To review the patch, your best choice is probably to read the new version of
createReduxStorefrom start to finish. I added plenty of comments that explain step by step what is going on.This is a follow up to discussion started in #51413 (comment).