-
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
Data: Build the basic data controls into every store #25362
Conversation
Size Change: -580 B (0%) Total Size: 1.18 MB
ℹ️ View Unchanged
|
i'm not sure about this PR tbh, I think the "syncSelect" control is small enough that duplication is probably better than having the ap-fetch dependency there. |
I tend to agree that the pros don't outweight the cons here. It shows, though, that there might be something slightly wrong with the The select/dispatch controls are so close to the data stores so that they could be part of the |
I agree here 💯 cc @nerrad |
Sounds very similar to the evolution of resolvers moving into the wp.data package. I'm not opposed to this being built-in to wp.data by default. Built-in controls would also get rid of the gotcha folks encounter with not defining a controls object when registering a store and that resulting in resolvers not working. Would we deprecate the |
That's one of the options: it would be deprecated, and implemented as a thin wrapper around the builtin Of course, we'd need to find a new home for the We could also fix the unfortunate naming of the There's one thing that's not great about moving the controls to the This is where the // import controls with nice names from dedicated package
import { select, dispatch } from '@wordpress/data-controls';
// and use them in my control
export function *myControl() {
yield select( 'core', 'foo' );
yield dispatch( 'core', bar() );
} |
Maybe we can export theme as "controls" variable, it's not tree-shakable but we have just three right? |
We intend to register some controls created by `createRegistryControl` as built-ins with every store. In order to do that, we need to break a dependency cycle where registry creation depends on store registration which depends on creating controls which depends on default registry. The solution is to remove the `defaultRegistry` binding, which is there only to satisfy a typechecker anyway, and doesn't have any runtime impact.
Instead of shipping them in a separate `data-controls` package and require the store author to register them, build them in into every store.
The implementation and the unit test have been moved to the `@wordpress/data` package. The `data-controls` package now exposes only legacy aliases.
…rols Updates unit tests of actions (in `block-directory`, `edit-site` and `core-data`) that inspect the internal properties (like `type`) of controls that the action generator yields. A test that verifies if the action _behaves_ correctly wouldn't need to be changed like that.
66cf456
to
c2afe8b
Compare
I completely reworked this PR by moving the data controls ( I also wrote a brand new unit test for the controls. I didn't like the original The The last commit migrates the |
packages/data-controls/src/index.js
Outdated
args, | ||
}; | ||
} | ||
export const dispatch = dataControls.dispatch; |
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.
do you think we should deprecate these?
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.
Yes, deprecation would discourage folks from adding new usages of data-controls
. I guess the data-controls
wrappers should use the @wordpress/deprecated
helper?
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.
@youknowriad I updated the data-controls
wrappers to warn about deprecation using the @wordpress/deprecated
package, in 51f7fc5.
But now I have problems with unit tests that I don't know how to solve: every unit tests uses the jest-console
plugin that checks that the code didn't produce any console messages. But the deprecated()
function logs the deprecation messages with console.warn()
, so many unit tests for code that still uses the deprecated controls now fail.
Is there any established way how to get out of this?
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.
Yes, we have some asserters to aknowledge that warnings will be thrown. expect( console ).toHaveWarned();
That said, when we introduce deprecations, we do it after refactoring the Core usage of this API. Do we still have existing places where these APIs are used on Gutenberg?
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.
Do we still have existing places where these APIs are used on Gutenberg?
Yes, the data-controls
are still used in many stores. It will take some 5+ PRs to migrate them one by one.
At this moment, it seems to me the best option is to mark the data-controls
as deprecated only after that migration is finished. It shouldn't take long after this PR is merged.
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.
it seems to me the best option is to mark the data-controls as deprecated only after that migration is finished. It shouldn't take long after this PR is merged.
👍
* | ||
* @type {WPDataRegistry} | ||
*/ | ||
selector.registry = defaultRegistry; |
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 this some useless leftover?
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 described the motivation for this in the commit's commit message:
We intend to register some controls created by
createRegistryControl
as built-ins with every store. In order to do that, we need to break a dependency cycle where registry creation depends on store registration which depends on creating controls which depends on default registry.The solution is to remove the
defaultRegistry
binding, which is there only to satisfy a typechecker anyway, and doesn't have any runtime impact.
Another solution would be to break up the factory.js
module and put createRegistrySelector
and createRegistryControl
into separate modules. createRegistrySelector
has the offending defaultRegistry
dependency, while createRegistryControl
is needed to create a store and therefore introduces a cyclic dependency.
However, to make the API really type-safe, we'd need to rethink how we create the selectors and introduce types like UnregisteredRegistrySelector
and RegisteredRegistrySelector
. Right now, the usage is like:
const selector = createRegistrySelector( ( select ) => ( state ) => { select( 'core' ) /* ... */ } );
// at this moment the selector is in a weird state where it's either unbound or bound to `defaultRegistry`
// it's not entirely certain whether the following call should crash or not and what `value` is supposed to be
const value = selector( state );
// only after this registration is the `selector` registered and has 100% defined behavior
customRegistry.registerStore( 'mystore', { reducer, selectors: { selector } } );
// this second call can have an entirely different result from the first one, although the `selector`
// value is still the same and has the same type. The `selector` properties have been mutated during
// `registerStore`.
const value = selector( state );
I.e., the code is not safe and I don't immediately see how introducing types could prevent the unsafe usages.
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'm not sure i understand everything here but I agree that depending on the default registry should be avoided anyway. The default registry only exists because it was there first. If we'd start over, we'd probably avoid it entirely.
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'm not sure i understand everything here but I agree that depending on the default registry should be avoided anyway.
The tl;dr is that the default registry reference started introducing dependency cycles 🙂
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 👍
Thanks for the review @youknowriad 👍 I'll check if unit tests are indeed green after the deprecations have been commented out, and then will merge the PR. |
In the
@wordpress/block-editor
package, replaces the home-grownSELECT
control withSYNC_SELECT
from@wordpress/data-controls
.There is one thing in this PR I don't like very much: the
@wordpress/block-editor
becomes indirectly dependent on@wordpress/api-fetch
, although it never uses that code. Thecontrols
object exported from@wordpress/data-controls
contains theAPI_FETCH
field. Although we don't use it, it's there, and it's not even possible to tree-shake it away. It's a field of an exported object, not a standalone export.How bad is that?