google / site-kit-wp

Site Kit is a one-stop solution for WordPress users to use everything Google has to offer to make them successful on the web.
https://sitekit.withgoogle.com
Apache License 2.0
1.25k stars 291 forks source link

Refactor actions and resolvers with `wp.data` controls #8992

Closed aaemnnosttv closed 1 month ago

aaemnnosttv commented 4 months ago

Feature Description

With our recent upgrade of @wordpress/data, the package now includes a set of controls which are essentially utility actions that every store will have associated controls for.

These are

These are actions meaning we would yield these within our own actions/resolvers instead of using workarounds to getRegistry and commonActions.await just to get access to select/registrySelect or dispatch and await the result.


Do not alter or remove anything below. The following sections will be managed by moderators only.

Acceptance criteria

Implementation Brief

Test Coverage

QA Brief

Changelog entry

tofumatt commented 3 months ago

@zutigrm Let's do the opposite, starting with one module. That way the number of files/modules/etc. to test/review is smaller, and the QA can be scoped to testing Analytics behaviour.

If during development there's time to work on more modules they can be added I think.

It's missing from the ACs, but part of this change should include us exporting these new controls from googlesitekit-data, which is also where we should be importing them from.

I think we can mirror the @wordpress/data exports and export things as controls, but if you wanted to alias it to builtInControls so it can be easily imported without every file needing to do { controls as builtInControls } that'd be nice, given how many of our files already have a const controls variable. 👍🏻

Builtin controls can be used in following way: select|resolveSelect|dispatch( storeKey, selectorName, ...args ) , so const propertyID = registry.select( MODULES_ANALYTICS_4 ).getPropertyID() would be replaced with: const propertyID = builtinControls.select( MODULES_ANALYTICS_4, 'getPropertyID' ), etc.

I get what this means but it's a bit hard to read/parse. I think it's fine to write something like:

Replace registry.select with builtInControls.select, registry.resolveSelect with builtInControls.resolveSelect, and registry.dispatch with builtInControls.dispatch.

aaemnnosttv commented 3 months ago
  • Builtin controls can be used in following way: select|resolveSelect|dispatch( storeKey, selectorName, ...args ) , so const propertyID = registry.select( MODULES_ANALYTICS_4 ).getPropertyID() would be replaced with: const propertyID = builtinControls.select( MODULES_ANALYTICS_4, 'getPropertyID' ), etc

I just want to flag that the example here is incorrect. The controls export is an object of (unbound) action creators in Redux terms. These are then mixed-in with their associated controls (to handle their respective actions) when registering a store.

As mentioned in the description:

These are actions meaning we would yield these within our own actions/resolvers instead of using workarounds to getRegistry and commonActions.await just to get access to select/registrySelect or dispatch and await the result.

Calling the function returns the raw action object, so we need to yield them to dispatch them on the current store.

wpd.controls.select('store/foo', 'getBar', 'argBaz', 'argBuzz')
// returns:
{
  type: '@@data/SELECT',
  storeKey: 'store/foo',
  selectorName: 'getBar',
  args: [ 'argBaz', 'argBuzz' ]
}
zutigrm commented 3 months ago

Thanks @aaemnnosttv indeed, I updated to reference that they should be yielded to return the result.

@tofumatt Thanks for the suggestion, I update IB to mention adding alias for controls to our data package, and applied suggested wording.

tofumatt commented 3 months ago

We should be explicit in the IB that not all registry.select calls can be replaced. For instance, any code inside a createRegistryControl is fine to leave as-is (eg. https://github.com/google/site-kit-wp/blob/dc89f6c19d3d1103e5be3387c2739fe2955324bc/assets/js/googlesitekit/data/create-existing-tag-store.js#L103-L104).

Let's also make a plan to mark getRegistry as deprecated as part of this issue to discourage future use, as the ACs call for it.

zutigrm commented 3 months ago

Thanks @tofumatt , that's a good spot. I amended the IB to include those points. I suggested the depreciation error for eslint rule to ensure it is not used. Let me know what you think

tofumatt commented 3 months ago

I meant a JSDoc @deprecated notice for now; once all actions are converted we should remove commonActions instead of marking it as deprecated, but we'll do that once all datastores are migrated.

I adjusted the IB to account for this, and increased the estimate slightly in case any issues are encountered; if they aren't, more work can be done on other stores.

IB ✅

tofumatt commented 2 months ago

After a discussion with @aaemnnosttv, @eugene-manuilov, and @nfmohit, we're actually going to change the scope of this issue after looking at the resulting PR (#9234), which ends up being a worse API 😅

I'm just updating that PR and will move it to CR soon; I've updated the ACs accordingly.

aaemnnosttv commented 2 months ago

No QA to do here, moving to approval 👍