-
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
DataViews: Support passing the registry to actions callbacks #62505
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -327,28 +327,16 @@ interface ActionBase< Item extends AnyItem > { | |
|
||
export interface ActionModal< Item extends AnyItem > | ||
extends ActionBase< Item > { | ||
/** | ||
* The callback to execute when the action has finished. | ||
*/ | ||
onActionPerformed: ( ( items: Item[] ) => void ) | undefined; | ||
|
||
/** | ||
* The callback to execute when the action is triggered. | ||
*/ | ||
onActionStart: ( ( items: Item[] ) => void ) | undefined; | ||
|
||
/** | ||
* Modal to render when the action is triggered. | ||
*/ | ||
RenderModal: ( { | ||
items, | ||
closeModal, | ||
onActionStart, | ||
onActionPerformed, | ||
}: { | ||
items: Item[]; | ||
closeModal?: () => void; | ||
onActionStart?: ( items: Item[] ) => void; | ||
onActionPerformed?: ( items: Item[] ) => void; | ||
} ) => ReactElement; | ||
|
||
|
@@ -368,7 +356,13 @@ export interface ActionButton< Item extends AnyItem > | |
/** | ||
* The callback to execute when the action is triggered. | ||
*/ | ||
callback: ( items: Item[] ) => void; | ||
callback: ( | ||
items: Item[], | ||
context: { | ||
registry: any; | ||
onActionPerformed?: ( items: Item[] ) => void; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the Is it possible to make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it makes more sense to put the context as the last argument since it's not really necessary for the callback. The "items" is more important. Also, one of the reasons, I made it an object is to be able to add more optional configs later there. For the onActionPerformed, yes it's used in both post and site editors (but not in dataviews). I don't love this API personally, but I don't want to change everything here. It can potentially be made unnecessary in callback actions by making these functions return promises but it will be necessary in Modal Actions as a prop, so maybe it's fine to keep it for callback actions as an argument too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The downside is that if you ever add new parameters (how likely is that?) then |
||
) => void; | ||
} | ||
|
||
export type Action< Item extends AnyItem > = | ||
|
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.
From the point of view of a consumer that wants to use the
@wordpress/dataviews
package in its own screens, what's aregistry
?I lack context on the way we are evolving actions and how this helps, so I'd like to learn more why we want to tie
wordpress/dataviews
towordpress/data
concepts.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.
cc @youknowriad @ntsekouras @jsnajdr
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.
Registry just allows to any wordpress store. It doesn't introduce a dependency to a particular store but it allows dataviews actions to trigger actions from any store.
We used to that by having "React hooks" that actually return action but that is not ideal IMO. I prefer for dataviews actions to be global registrable objects just like blocks for instance.
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.
Oh yes I understand the complaint and I think it's very valid 🙂 This PR makes the
dataviews
library dependent ondata
, even though it doesn't really use it. It just retrieves theregistry
and passes it to actions. And most actions won't use theregistry
at all. But thedata
library still needs to be present because theuseRegistry
calls are happening all the time.A much more flexible approach would be if the
context
was empty by default, and you would configure it when creating a dataview. I'm not very familiar with dataviews, but something like this might work:A certain app like
edit-site
wants to passregistry
to its actions, so it configures itsDataViews
accordingly. The library is completely unaware about what's in thecontext
, and other apps can put something completely different there.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.
Jarda, your example illustrates a lot better the point, thanks. I still like to clarify why the "context" needs to be passed through the DataViews API if it is not used/modified by it. Cannot the actions retrieve whatever extra data they need?
I understand a valid use case for having to pass something through would be the following: the action's callback needs to have something ready when it is called. Is this the case? If so, could we do something along these lines instead?
I reckon this is still part of what DataViews has to do (passing the callbackContext to the callback), though the locality makes it easier to reason about (it feels it's part of the Actions API and not of DataViews API) — with the added benefit that each action can have a different context.
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.
Obviously, it's possible to call the registration action within a hook as well but it does make extensibility a bit harder. When should a third-party script "unregister" a default provided core action.
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.
What I don't like as well, is that it will actually forces us to retriggers the whole registration action when a selected value used with
isElligible
is resolved (for instance, when the active rendering mode changes, or active post type, or user permission...)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 this sounds similar to what I also write above: often it's a good idea to define actions and the context separately and independently. It's then up to framework to inject all the dependencies (context) when calling the action.
It's worth exploring passing the context (or context creator function) to
DataViews
as prop.Is the context passed to
isEligible
different from the context passed to the action callback?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.
Now, that I think about it more, there's a use-case that can't really be solved with the approach suggested #62505 (comment)
Show/hide an action by checking the permissions for the current item(s). Permissions changes from one row to the other in a data view, so how would you define an action who
isEligible
call should use a selector value (canUser
). The only possibility I see is to register/unregister the action when the selection changes. It doesn't seem very ergonomic or DevX friendly to me.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.
Not really the same, but a similar sacrifice was made here: #60724