-
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
API Reference Docs for Interactivity API #52948
Conversation
Flaky tests detected in 5bf1979. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5726713376
|
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.
Hey Juanma, amazing job. I think it's a great first version 🙂
Some comments below:
I'd sort the directives in a way that makes more sense from a learning journey perspective. For example:
data-wp-context
data-wp-bind
data-wp-class
data-wp-style
data-wp-text
data-wp-on
data-wp-effect
data-wp-init
data-wp-body
The other ones are still upcoming, so I don't know if we should document them yet or not. Probably not. Although maybe we could say that they are coming:
data-wp-show
data-wp-each
data-wp-dangerous-html
data-wp-slot/fill
data-wp-error
It's true that wp-show
is still on the codebase but I want to remove it today. We haven't figured it out yet, so I prefer that people use data-wp-bind--hidden
or data-wp-style--display
to conditionally hide/show elements for now.
There are other ones that are a bit special and we should also document, but we can leave that for later:
data-wp-interactive
data-wp-ignore
data-wp-key
Maybe we could mention what is the directive value. I.e., for the majority of them, it would be something like:
It accepts a reference that points to a specific callback of the store. That callback is then executed when ___ happens and the value that it returns is used to ___.
data-wp-bind--attribute
:- Executed when the element is created, and then each time that any of the properties of the
state
orcontext
used inside the callback changes.- The callback receives the attribute name:
attribute
.
- The callback receives the attribute name:
- The returned value is used to change the value of the associated attribute.
- If the value is
true
, the attribute is added:<div attribute>
. - If the value is
false
, the attribute is removed:<div>
. - If the value is a string, the attribute is added with its value assigned:
<div attribute="value"
. - If the attribute name starts with
aria-
ordata-
and the value is boolean (eithertrue
orfalse
), the attribute is added to the DOM with the boolean value assigned as a string:<div aria-attribute="true">
.
- If the value is
- Executed when the element is created, and then each time that any of the properties of the
data-wp-class--classname
:- Executed when the element is created, and then each time that any of the properties of the
state
orcontext
used inside the callback changes.- The callback receives the class name:
className
.
- The callback receives the class name:
- The returned value is used as a boolean to toggle (add or remove) the associated class name from the
class
attribute.
- Executed when the element is created, and then each time that any of the properties of the
data-wp-style--cssproperty
:- Executed when the element is created, and then each time that any of the properties of the
state
orcontext
used inside the callback changes.- The callback receives the style property:
styleProperty
.
- The callback receives the style property:
- The returned value is used to change the value of the associated CSS property:
<div style="cssproperty: value;
.
- Executed when the element is created, and then each time that any of the properties of the
data-wp-text
:- Executed when the element is created, and then each time that any of the properties of the
state
orcontext
used inside the callback changes. - The returned value is used to change the inner content of the element:
<div>value</div>
.
- Executed when the element is created, and then each time that any of the properties of the
data-wp-on--event
:- Executed each time the associated event is triggered.
- The callback receives the event:
event
- The callback receives the event:
- The returned value is ignored.
- Executed each time the associated event is triggered.
data-wp-effect
:- Executed when the element is created, and then each time that any of the properties of the
state
orcontext
used inside the callback changes. - It can return a function. If it does, the returned function is used as cleanup logic, i.e., it will run just before the callback runs again, and it will run again when the element is removed from the DOM.
- Executed when the element is created, and then each time that any of the properties of the
data-wp-init
:- Executed when the element is created.
- It can return a function. If it does, the returned function will run when the element is removed from the DOM.
wp-context
accepts a stringified JSON, and wp-portal
doesn't accept anything.
// render.php | ||
wp_store( array( | ||
'state' => array( | ||
'myPlugin' => array( |
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.
Maybe we should keep using myNamespace
here for consistency?
'myPlugin' => array( | |
'myNamespace' => array( |
@luisherranz It would be great to have an issue for each directive or a Tracking Issue we could link in the docs to help explain these directives are in progress |
@luisherranz Thanks a lot for the feedback 🙏 |
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.
Very nice, Juanma! This is shaping quite nicely. I like the examples. They are simple and easy to follow but still enough to learn the concepts 🙂👏
I've added a few extra suggestions and corrections below but I'm preemptively approving it so you can merge it whenever you think it's ready.
The `wp-interactive` "activates" hydration for the DOM element and its children through the Interactivity API (directives and store). | ||
|
||
> **Note** | ||
> The use of `wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `wp-interactive` has not been added for the sake of simplicity |
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 use of `wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `wp-interactive` has not been added for the sake of simplicity | |
> The use of `wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `data-wp-interactive` directive has not been added for the sake of simplicity. |
The `wp-interactive` "activates" hydration for the DOM element and its children through the Interactivity API (directives and store). | ||
|
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.
Maybe we can add an example?
Also, maybe we should stick to "interactive" and "interactivity" and avoid the use of hydration, which is a more technical term?
The `wp-interactive` "activates" hydration for the DOM element and its children through the Interactivity API (directives and store). | |
The `wp-interactive` directive "activates" the interactivity for the DOM element and its children through the Interactivity API (directives and store). | |
\```html | |
<!-- Let's make this element and its children interactive --> | |
<div data-wp-interactive> | |
I'm interactive now, and I can use directives! | |
<span> | |
I'm also interactive, and I can also use directives! | |
</span> | |
</div> | |
\``` |
|
||
#### `wp-effect` | ||
|
||
It runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax`data-wp-effect--[unique-id]`. |
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 runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax`data-wp-effect--[unique-id]`. | |
It runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax `data-wp-effect--[unique-id]`. _The unique id doesn't need to be unique globally, it just needs to be different than the other unique ids of the `wp-effect` directives of that DOM element._ |
|
||
It runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax`data-wp-effect--[unique-id]`. | ||
|
||
_Example of `wp-on` directive_ |
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.
_Example of `wp-on` directive_ | |
_Example of `wp-effect` directive_ |
As a reference, some use cases for this directive may be: | ||
- logging. | ||
- changing the title of the page. | ||
- setting the focus on an element with `.focus()`. |
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.
As a reference, some use cases for this directive may be: | |
- logging. | |
- changing the title of the page. | |
- setting the focus on an element with `.focus()`. | |
As a reference, some use cases for this directive may be: | |
- logging. | |
- changing the title of the page. | |
- setting the focus on an element with `.focus()`. | |
- changing the state or context when certain conditions are met. |
|
||
The store is used to create the logic (actions, effects…) linked to the directives and the data used inside that logic (state, selectors…). | ||
|
||
**The store is usually created in the `view.js` file of each block**, although it can be initialized from the `render.php` of the block (see [diagram](https://excalidraw.com/#json=FPTvzmKpyunGuFzWt5nzX,gs2vvsN0HEvnEHsQ9u1gPg)). |
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 entirely sure that this diagram adds any value here. It seems difficult to understand without more 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.
You're right! I'll remove it from now and may use it in another more advanced explanation somewhere else
- **Global state**: It is defined using the `store()` function, and the data is available to all the HTML nodes of the page. | ||
- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. |
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.
Maybe we can add examples.
- **Global state**: It is defined using the `store()` function, and the data is available to all the HTML nodes of the page. | |
- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. | |
- **Global state**: It is defined using the `store()` function, and the data is available to all the HTML nodes of the page. It can be accessed using the `state` property. | |
- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. It can be accessed using the `context` property. | |
\```html | |
<!-- Access global state --> | |
<span data-wp-text="state.someText"></span> | |
<!-- Access local state (context) --> | |
<span data-wp-text="context.someText"></span> | |
\``` | |
\```js | |
store( { | |
actions: { | |
someAction: ({ state, context }) => { | |
state.someText // Access or modify global state | |
context.someText // Access or modify local state (context) | |
}, | |
}, | |
} ) | |
\``` |
|
||
#### Selectors | ||
|
||
Also known as _derived state_, returns a computed version of the state. |
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.
Also known as _derived state_, returns a computed version of the state. | |
Also known as _derived state_, returns a computed version of the state. They can access both `state` and `context`. |
} ); | ||
``` | ||
|
||
### Objects passed to callbacks |
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.
### Objects passed to callbacks | |
### Argument passed to callbacks |
|
||
When a directive is evaluated, the reference callback receives an object with: | ||
|
||
- The **`store`** containing the `state`, `actions` and `effects`. |
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 **`store`** containing the `state`, `actions` and `effects`. | |
- The **`store`** containing all the store properties, like `state`, `selectors`, `actions` or `effects`. |
What?
API Reference Docs for Interactivity API
Why?
Solves #52922