-
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
iAPI Docs: Understanding global state, local context and derived state #63930
iAPI Docs: Understanding global state, local context and derived state #63930
Conversation
After a first read, the guide looks amazing! 👏 I think these are key concepts to understand while using the Interactivity API and this pull request does a great job explaining them. I might be biased because I was already familiar with the terms, but I like how it is structured. I feel the explanations including "When to use X" and the different examples are really useful. I'll try to take a deeper look once you consider it ready. |
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.
Great to see this type of guide added as it will help to onboard developers. Thank you so much for working on it 👏🏻
It sounds like a good direction with the nomenclature of global state vs local context. I did the first pass with the focus on the global state and left my feedback inline. I intend to have a look at local context next, but I might have other priorities in the next days so feel free to proceed based on feedback from other contributors 😄
One thing that isn't fully clear from this guide is what are the best practices for calling wp_interactivity_state
. Where devs should locate the code call, inside the main plugin file vs inside the render_callback
of the block type, and what are the implications of that. That might apply to store()
calls as well, when I think about it now, too.
|
||
### When to use global state | ||
|
||
- You need to share data between multiple blocks that are not directly related in the DOM hierarchy. |
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.
One crucial aspect that is important to clarify is the nuances of how developers should handle multiple blocks of the same type, e.g., several Image blocks rendered on the page, in contrast to how that would look like in the case where two different block types would like to share the same global state, ex. the Gallery block and the Image block set as the child, or the Navigation block and some completely custom block type that would interact with it from a completely random place on the page.
|
||
```html | ||
<span | ||
data-wp-bind--hidden="!state.shown" |
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.
For education purposes, will this magically read the value from the myPlugin
namespace if there is no wp-data-interactivy="myPlugin"
set higher in the HTML tree?
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.
No, we can add data-wp-interactive
to make it clearer, thanks!
The global state initialized on the server using the `wp_interactivity_state` function is also included in that object: | ||
|
||
```php | ||
wp_interactivity_state( '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.
Was it intentional to reuse the same namespace myPlugin
as in the first example for declaring server state? Later the docs state:
Lastly, all calls to the
store
function with the same namespace are merged together:
In effect, I was wondering if at this moment I should assume that the store contains:
counter
,shown
,example
-wp_interactivity_state
firs callisLoading
-store
first callsomeValue
-wp_interactivity_state
second callotherValue
-store
second call
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 it's not very clear. I'll think it over about the example in this guide. Thanks!
|
||
store( 'myPlugin', { state: { otherValue: 2 } } ); | ||
|
||
// All calls to `store` return a stable reference (the same object). |
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 is the same object
in this context? It would help to clarify it further.
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.
Ok, I'll try to improve it, thanks!
|
||
```php | ||
<?php | ||
wp_interactivity_state( '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.
It's getting confusing to see the same namespace myPlugin
referenced again. What would be the recommendation for plugin authors when picking the namespace name? Should they use one for their plugin, split by block types?
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 want to create a specific guide that explains namespaces and scope.
wp_interactivity_state( 'myPlugin', array( | ||
'counter' => 1, // This is global state. | ||
'double' => 2, // This is derived 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.
What alternatives are there to explain the idea of a derived state with the first example presented? I often saw something similar to the following:
wp_interactivity_state( 'myPlugin', array( | |
'counter' => 1, // This is global state. | |
'double' => 2, // This is derived state. | |
)); | |
$counter = 1; | |
wp_interactivity_state( 'myPlugin', array( | |
'counter' => $counter, // This is global state. | |
'double' => 2 * $counter, // This is derived state. | |
)); |
When placing the value, it isn't immediately clear that double
is computed from other entries in 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.
Good suggestion. I will apply it to the guide. Thank you!
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.
In general this helped my understanding of global state, local context, and derived state. I was able to clean up the store of something I'm working on and feel more confident in the implementation, after reading this guide.
|
||
- **Initializing the derived state** | ||
|
||
Typically, the derived state should be initialized on the server using the `wp_interactivity_state` function in the exact same way as the global 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.
Why typically? Because you often depend on values from the server (e.g. block attributes) to calculate the initial values of 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.
I have created a specific guide to explain server-side rendering and how directives are processed on the server. It's part of this PR:
Hopefully, it will answer your question.
(Feedback welcomed on that guide too 😄)
</div> | ||
``` | ||
|
||
In the client, the derived state is defined using getters: |
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.
To me, this is the key difference between derived vs global state, and could be presented much earlier in the guide. That could just be how I learn though.
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.
Alright, I'll take a look to see if it can be mentioned earlier. Thanks, Jeff!
I am closing this pull request in favor of this one where I have merged this guide with the other two initial guides: |
What?
Following up on The Reactive and Declarative Mindset guide, this is the second guide of the new Core Concepts section of the Interactivity API, focusing on explaining the concept of state and the different types of state (global, local, and derived) used in the Interactivity API.
Why?
The Interactivity API would benefit from some guides that explain the concepts and mental models, not just from the API references.
How?
For now, I have simply added the guide as a markdown file.
The work to generate the new Core Concepts section is in the pull request for the guide for reactive and declarative mindset. So, once that pull request is merged, we can change this one to fit that format.