Interactivity Router

## Metadata
- Author: [[YouTube]]
- Full Title: Interactivity Router
- Category: #articles
- Document Tags: [[development]] [[h1]] [[optimization]] [[wordpress]]
- Summary: Interactivity Router
- URL: https://www.youtube.com/watch?v=hlbT0fnIe8E
We are live.
Hello there. How you doing?
say hi in the chat if you are there.
Okay.
So
in today's session I want to talk about
the
interactivity router
which is a package that comes with the
interactivity API.
So this package is
already enabled in some parts of the WordPress core blocks. For example, the query loop block. Let me try to the query loop block has a toggle and the query loop block by default it triggers a full reload of the page.
But we can set this block to do a client side navigation which means that not the full page will be loaded only the specific portion of the HTML that needs to be rendered. What's the advantage of this? The HTML
is going to be loaded, but the amount of HTML that is going to be processed by the browser is going to be only a little portion of it. Let me see if I can configure the query loop block to have client side navigation.
So by default we come here. Okay. I only have one post. Let me create. There is this plugin called faker which I like a lot to create like to create a lot of fake post. For example, I want maybe 20 posts or something like that.
I activate this. Here I can select maybe 25 because by having several posts we can we can check how the query loop block in its pagination
it only loads the specific portion of it. Okay. So, the posts are generated. If we go to appearance and editor in this template, for example,
we have a query loop block here. If we go to the advanced section, we can see this toggle which is disabled because we are in 6.8 and this is one of the new things coming in WordPress 6.9 for the for the interactivity routter.
The thing is that we couldn't disable this because by default is full page. But if we disable this, we can enable client side navigation with the query loop block. But right now we are in WordPress 6.8. So, let's update. I think I'm going to
lose the the posts that I have created. But anyway, let's load 6.9. Let's go to Yes, I have lost. Well, it's very quickly. Okay, I want to install this plugin.
I want to activate this plugin and I want to create 25 for example. Nice. So what I want to do is to show how the query loop leverages the interactivity router package. In order to do that, I have created a
lot of posts. And if we visit the site and we inspect the page and we go to network and I filter by doc. Every time that I go to a new page, I'm going to get a new
doc, which means there's a full page reload. We're getting a new document, which means that the whole HTML is fetched, but also the whole HTML is processed in the browser. So a way to avoid to process the whole HTML because we
don't need to process the whole HTML. We only need in this case this area. We don't need to process the header again. We don't need to process all this footer. We just need to update this specific portion. One way to do that is to enable client side navigation and the interactivity API allows that. And the query loop block
allows us to do that with a toggle that can be disabled by default. The quil loop block uses like full page. So if we go
edit side here we are editing this template. If we go here to query loop and we go to advanced now because we are in WordPress 6.9 we should have this. This is related to one of the updates coming in WordPress 6.9 for the
interactivity router. The specific update that is related to this is this one. The thing is that it was disabled because when there was a navigation to a page that had some block that require to load the script modules
that those blocks didn't work because those modules those modules weren't loaded. This has been fixed in WordPress 6.9 and this fix has allowed this feature to to be enabled. I mean now we can disable this. We can save. And when we navigate through pages using
the query loop block, we will see how there's no full page reload anymore. So let's check that. If we inspect the page and we go to network, maybe what I can do is to
select less elements per page. This is something that I can set here in custom. H maybe I don't know three per page. Okay, with these elements per page and if I inspect
and we go to network and we filter by doc and we select next page. We can see how there's no a new document loaded directly from the browser.
But what we are doing is retrieving those pages, the HTML of those pages. We are getting them by using a fetch in the background. We can see we click another one. We can see we are doing this. So the HTML is here
and what the interactivity router and interactivity API is doing is getting the HTML comparing with the current HM HTML and just update the difference in that section that is defined as uh routter region I think is the the right name. Okay. So this is more or less the
idea of the interactivity router. Another thing that we can do here is for example, let me go to the post one.
If I edit this post And for example, I'm going to add here an image. For example, this one. And what I'm going to do is alert on click.
because this behavior is powered by the interactivity EBA. So what I want to prove is this thing that when inside of router navigation, no interactivity router navigation or client navigation through the different regions.
The blocks that are inside those regions can be interactive as well. Okay. If I save If I save
Okay. So we have saved this post where we have added an image and that image now have lightbox behavior. So now if we go to the
query loop, we can see how inside the query loop we can have this behavior working. And this is working. As you can see, it has some directives here that will be onload and blah blah.
And there's also an attached to somewhere. Let me see. Touch to here. Data region rout.
So the thing the thing that happened here How are you? I'm talking here about the interactivity router. All good. Good to know. Are you familiar with the interactivity
routter? I've been working with um that this week a lot. I've been reviewing the documentation and I feel much more comfortable with it now. Yeah. So yeah, the thing about the interactivity routter is that it's actually applied in some parts of WordPress core. I was just explaining that
in the query loop for example is implemented and it allow us to it allows us to do navigation as an single page application. You know the concept of this single page application where the navigation is controlled by the client. So we can do something like that now with the interactivity router.
I have here an a really cool example. Let me see if I can find it. This is a very simple. This is something that I have borrowed from from Luis which is the mastermind behind um the interactivity API
and this is a implementation of the interactivity routter and interactivity AP. PI in raw HTML. I mean we can really these are MPN components that we can use in in different environments because they encapsulate some logic and some APIs
that can be used even outside of WordPress. The good thing about these packages is that they are they have been implemented with the mindset of WordPress blocks and the on the block paradigms. So they are fully compatible with how blocks work, but they can also be used outside the WordPress installation. And this is interesting if we want just to very
quickly test these packages and the API they provide. For example, here we have a a little app that uses some directives of the interact 3D API but also some regions. I'm going to create here a scaly draw.
I have a started here one. So this is the idea of the interactivity router. We have here um page A, we have page B and we have page C. and they are almost the same
but there are some regions that I want to update. So here something like this. something like this and something like this.
So we have three pages and the usual thing we would do is there any repo with um okay so mag is asking if there is any repo with examples of the interact with the API because he wants to see examples and
ideas of blocks. Okay. Um yes there are let's start from the documentation which is the uh which is the best place to start. If you go to the if you go to developer.workwordpress.org you can find here different handbooks. There is one about the block editor and here in the block editor there's the documentation about interactivity
API. So here in the interactivity API section I'm going to share a link in the chat at the end you can see here docs and examples and here you have some examples some really good examples for example there's a showcase discussions which is
really interesting because people have been publishing here the different applications of the interactivity API. So these are here you can find a lot of ideas and another good resource is the block development examples which is this compilation of examples
using the APIs provided by WordPress for blog development. I'm the main maintainer of this repo. So, I created this little app. I'm going to also share this in the chat. And the good thing is that you can very quickly find the examples you want by
selecting the right tax. For example, there is attack for the interactivity API and here you have a few examples and the good thing about this app is that this page can be shared. So yeah, there are some examples here and for each example
you have a live demo and you have the zip so you can download directly. This this each example is a plug-in. So you can just throw this folder into the plugins folder of your WordPress installation and you can just uh try the behavior. For example, this one interactivity API quiz block. You can
see here the code and you can see here the live um live demo of that plug-in. For example, this is a a an implementation of a quiz singer of Leeppell was a plant. Yes, I'm a Leepperin fan. So, Revolver was of the of the Beatles.
Yes, as you can see only when I'm controlling this on the on the client only when I have answered all the questions I can check my answers. So um okay I know the answer because I wrote the the questions. H but now we can check the answers. Okay and we can reset and then we can say single was uh whatever
uh yes and whatever and we have only one correct we can. So yeah, this is an implementation and here in the code you can see how the there are two blocks actually one for each question and another one controlling the other blocks.
And here in the viewjs we can see how we have different stores and different actions. And for the other one we have okay this is the this is the main one and this is each question and for each question we also have
its own set of action actions its own set of state properties and so on. So yeah we can we can play and we can connect the different um different blocks. One interesting thing is that with project store FA
with play store FA. One interesting thing is that these two blocks they share a specific name space. So when I define two different blocks that share a name space, I can share information. So I can do things in one block and I can make the other block to react to that to that change. So that's really cool.
I think the most complex thing. Okay, so Maggot is asking um I think the most complex things right now is to understand when to use the state, when to use the context. But I but he's he's getting the thing. Yeah. Yeah. There are also in the documentation some guides and for example here it's a really good article about each concept.
um that I think um yeah it provides some guidance uh in that sense. the my the way I see it right now is that the local context or the the local context makes sense
when the information is only relevant to a specific portion of the DOM and that can be very small. It can be a div, it can be a ul. Um, it's a way to to isolate one portion of code only to affect a specific uh portion of the DOM. The global state makes sense when the
information the state variables the all that information that I want to store and manage and modify. I wanted to affect different portions of the DOM inside a bigger inside the the inside the block inside the HTML that is
managed by the block. In that case, I think the global state is interesting. It's true that we could also use like a context on the top level, but in that case, um, you can decide. The interesting thing about the global state is that you can share the information of the global state with other blocks. And that's where things get interesting.
If you define local context, I don't think let me check that I don't think you can access from the outside to that information but with the global estate you can access that information from other blocks and there's this demo of this deb
that showcase what is saying here. For example, here's a a block and here's another block. They both share a name space. But when I So this allows me to implement this type of effects. When I click here, this block reacts to the state variable that is in the name space that is shared by both blocks. So maybe
the data has been defined here. But as this block is also defined as part of the same name space, they can share information and they can share actions and they can share callbacks and they can share everything. So yeah, this is an example and as you can see it works all the time with all the blocks.
This is a really good example of of that. Okay, where was I? I think I have deviated a lot. Yeah, examples. There's also an example for interactivity router which is this one.
I don't think it's the best example in the world. I have a better one now. But yeah, it's an example of an implementation. The idea here is that we can I have four posts created and I can navigate through the content of each post without doing a full reload of the page. For example, when I click next,
this part doesn't change and I get the new content. And you can see here the specific attributes of the new block that is being loaded and the URL that is being loaded here. So yeah, this is an example of using the interactivity router. I have a better
example now. Let me just show you that very quickly. I'm still working off on it. But if I go here to quiz. Okay.
The idea I think this is a a better use case of using the interactivity router. Right now I have five posts. I have quiz and I have question one, question two, question three, question four. They are all built over a block.
So the information here is inside a block and also this block has an interactive block. So I can go here and this is uh this is a block that uses the interactivity API. Well, the idea is that I can go to a page. Maybe this could make sense not
as a post but as a page and then each question is a custom post type and they all share the same template. Something like that. I think it's the the best use case for this. So you can have even just a landing page. I I may do that. You can have just a landing page without any other type of navigation and you just enter directly into this quiz. And right now I'm randomly selecting questions.
And when I start each question has a time remaining and I cannot navigate I cannot navigate anymore to this question and I have 10 seconds right now. I don't have a way to provide an answer. I just want to test the interactivity router and the navigation.
But yeah, this is working fine. And we can see here if we go reset quiz well I can share the repository where I have this which is in
by the way if you are interested in following what I'm doing lately I have implemented this thing in my GitHub profile which actually I have like different GitHub profiles because my GitHub username is actually one my guitar
but I have different organizations to organize is the different areas um I've been working during my career. So when I started focusing more on WordPress, I created this Jamavp organization and here's where I do most of my work. Okay. So in this organization I have a landing page that
shares the activity I have had lately. For example, I automatically share here the latest posts that I publish. I have here my feature projects which are like the yeah the most interesting projects that I have and and you can see the activity I do on
them but also I share here the repositories that I have created lately. So here you can see the repository with the project I'm showing you. I going to share this in the chat as well and also some
repositories that I start and also some guests that I have. For example, this is a G that I use a lot. This is a a way a very quick way to detect to check if the custom blocks that I have defined are properly registered. If I in this,
if I go to the block editor, I need to be in the block editor, which means I need to have access to the doll BP global window. I can just launch this and this tells me the custom blocks that it so it goes through the list of all registered blocks and excludes from that array of objects. It excludes the core
blocks. So it just returns the custom blocks. So this is a pretty useful snippet that I use from time to time. So yeah, I was sharing this because I wanted to share this repository with this example, but also if you want to to check some other things I've been
working on lately, you can directly go to github.com/wama-b. Perfect. Let's continue. with this demo. If I go to rest quiz um we can see here in the console in the elements.
So this is when we navigate through different pages. I have here defined a interactivity routter region quiz. So this is the portion that is going to be updated whenever I navigate. As you can see if I go to question one you can see how things here have been highlighted which means that only this
portion of the DOM has been processed and updated. So this is the interesting thing. The whole page hasn't changed. And the only portion of HTML that has been updated in the browser is this uh new elements. So there's a div happening and the new parts inside this section are the ones that are updated.
Okay. Okay. Let me close conversations because I'm just uh jumping from one thing to another. But that's fine. This is just sharing the stuff out loud. Um okay, I have shared the samples. I have shared this. I have shared this and we were checking the documentation
about the global state local context and derived state and I was here. When we navigate through pages, we usually do that by clicking links and that provokes a full
page reload. But the the activity API router, if we go to the documentation, which is this one, the interactivity API routter provides two methods, two actions. One of the actions
is navigate. And the navigate method what it does is it fetches the page HTML and updates any interactive regions whose contents have changed in the new page. So if I navigate using normal navigation
the whole content is updated. But if I if I use navigate from the interactivity routt
Put that.
Then what happens is the following. I fetch the HTML of the new page.
Um, what I can do this? Okay, I'm going to do this. Do this full full um full. Okay, then
one. Nice. So I have this going to group
to create like different steps. We fetch the HTML of the new page. Then we
um get the the region. How is this called? Uh this we get extract extract the region
and Update in the DOM only the new the new parts
in the under the in the in the R region. This is um the part of the interactivity API that leverages React.
So I'm going to say here react.
Mhm. React is like a React. So this is more or less what a React application is doing. And every time I go to a new page using navigate, this is what's uh going on. So there's no a full page reload. only
the HTML is fetched via a fetch in the background and only not all the HTML is updated in the browser only a specific portions. How do we define those portions? By using the data lip routter region. So if we go to the application
see if I can show
Yeah, this is the code. This is the code. Um This is the code that I have and the demo is
here. Okay, this is the And here what I have is a a block using interactivity API.
To define a block with the interactivity API, we need to mark the block as supports interactivity true.
This is one of the requirements supports interactivity true. Then we need to create another thing is in the block.json JSON we need to define a view script module. This will make that in the build process
the bundle will be prepared to be loaded as a module in the in the client in the browser. Which means that if I go here for example the BUJS imports the
WordPress interactivity package if I don't use the experimental modules flag. What happens in the build process when I do WB scripts build is that this library gets bundled with
the final JavaScript which means that the JavaScript is going to be bigger. When we use the experimental modules, what we do is we serve this JavaScript as a JavaScript module in the browser. The browsers can manage
directly modules. So in the bundle this library is not going to be bundled in the final JavaScript. So the Vue.js is going to be lighter. So it's going to have less size. We can see here the Vue.js JS. It basically only
contains um our code. Yeah, it doesn't it doesn't contain anything else. And we can see here that we have an import that is going to be managed directly by the browser. So when we serve JavaScript modules
and the blocks provides different ways to do that very easily. So what do we need to do to serve a BUJS in a block as a module? The only thing we need to do is to define this view. JS as a view script module. And when we do the build, we just
add the flag experimental modules. When we do that, any import that we use in the Vue.js s is going to be imported directly in the browser. So let's check that. If we go to the demo when I load, let's see
network. Let's go to quiz. Okay, we can see how we can see how the interactivity API
engine is loaded independently. It's loaded before because there is a preload of the code. If we go to sources, no, if we go to elements, we can see here that the direct GBT API
reload. Yeah, we can see here how there's a module preload which means that is loaded independently but it's loaded just when the page starts loading and then WordPress at some point WordPress at some point it does the NQ script. So that's where the
that's where the let me see this is the one of the block library I guess maybe it's the navigation then we have the interactivity router
Wait. Uh, why can't it see address? I'm going to address. What else? Type script. Yeah, this is the one of our plug-in
and the interactivity API. So I have those packages loaded and then also the the navigation navigation it loads also like its own module. So here's the views of our plug-in. And one of the cool thing One of the cool things of JS modules is that I can
I can load. So in this case, let me see if we can we can have here a diagram. So we have the inter the activity interactivity API JS module module
um which is basically the activity API engine the JavaScript that contains all the logic behind the interactivity API. This is a module. This is um pre preloaded when the page uh starts uh starts being loaded
in the browser. The page starts being loaded in the proofs. Okay, this is um one model.
Then we have the the Vue.js the Vue.js file of our block of our custom block.
This Vue.js has import. It has this import blah blah blah. It has this import blah blah blah. So whenever
this happens, it automatically imports the JS model because it's already in the browser. It has been it has been loaded. has been preloaded.
But then at some point the code it does this which is really cool because when we trigger the navigation and what's happening here in the code is
that at some point in the on click in the on click we do navigate. So this is the navigation managed by the interactivity API router. This is when we are enabling this type of navigation. So what's happening is when we do on click
here we are dynamically loading the package that contains the logic of the interactivity router which is also super performant. And we have this
We have this and this it going to provoke the loading. in of another package
but only only when there's a click in that element. So as you can see all the APIs and all the workflows that are encouraged by the interactivity API and working in the background are very performant. They are thought
with performance in mind like uh making the requests and the process of HTML in the most effective way. Okay. Nice. So when I do click and in our example we were doing that here.
When I click on any of these elements and I can see this in the code here. I have a random selection of URLs that I am adding to the state.
I'm doing that here. random question slacks and using these directives I'm creating a loop and for each value I'm creating a link the text is managed by a state variable this is actually a derived state because item slack if I go
here item slack as you can see this is derived state which means that I am getting the context and for each item in the context I'm doing something to generate the final text. Okay, but the interesting thing is this actions navigate because every time I click on these links I'm not going to do a full page reload. I'm going to do a client side navigation
because actions navigate here is this. So what I'm doing here is I'm accessing the DOM element that triggered this method. I'm preventing the default. So the default event in the browser doesn't get
triggered is if I do if I don't do this I will get a full page reload. So I need to do this to stop any behavior in the browser because it's like saying it's like saying hey don't do anything else. I'm going to take control of things from now on. So what I'm doing is I dynamically import the
interactivity router and then I navigate using the actions uh navigate from the interactivity router. This is something that is documented here. If we go to the documentation, we can see how the package interactivity API exposes two methods. The navigate method and the prefetch method.
And the navigate method what it does is uh this is it fetches the HTML of the new page. It extracts the specific router region and it updates the the portion of the DOM that has been updated.
Nice. What else we can show from this demo? Okay, another interesting idea behind this um is the concept of a state in the client and a state in the server because with the interactivity API
we can define a state in the client. For example, here I have these props that are defined in the state. We have a name space which is interactivity router region quiz and under this name space I can define state variables. I can define actions call backs
and here I'm defining these props visited question slacks current timer page this is something that I'm defining in the client but when the page is loaded I'm also passing some initial values from the server And what's happening here is that
for every page I'm going to put this
This is the client. This is the client and this is the server.
Let me choose this. This is the server to be blue. This is going to be green. Okay.
So for the same name space let's call it a name space a or the same name space I have um state
Let me adjust this a little bit. Going to put this here. Okay. So, this is a state or name space opposite. This is going to be the name space and the state is this.
So we have defined a state in the in the server and and the client. So when when the page is loaded, I have some initial
values coming from the server which is what I define with the WP interactivity state. This allows me to define some initial values from the server and then when the JavaScript is loaded, I can also define some values in the client like for example this. What's happening here is that there is a merge
happening. There is a merge happening. And what I got here is
whatever came from the Whatever came from the server plus whatever was defined in the client. Going to express this a bit better.
Mhm. I'm going to express this a bit better. Um, put this
like this and this. Yeah, I think this is better. Something like this is better. A bit more clear.
So we have some initial state in the server. Then we have some initial state in the client. And we merge both. And in the client I finally have the two um the merge of the two states. But what happens when we do this navigation?
I can have something similar. So I can have here
I can have here some name space. That is the result of is the result of this
if the result of okay let me put this here and I'm going to put this here so we have in page A a state in the client that is result of the initial state defined in the server with this function plus the initial
state defined in the client here. Okay.
Mhm.
So, what happens when we navigate to a new page that has a new state
It has a new state. because now we have um two different states and we don't want to automatically
merge this because maybe we want to maybe use the val we are managing through the whole navigation. For example, in the quiz, I may want to, I don't know, keep track of the keep track of the different responses of the the the yes or nos or I
don't know. For example, um in this example, the initial page. Yeah, you can see how the first time the page is loaded, the state server and the state in the client
is the same. Well, in other words, the properties and the values that we have in the server match the ones we have in the client because there is a merge of the properties that we have defined for the server which represents this with the properties we have defined in
the client. We sends this and in the code this is the properties that we have defined the client and this is but what happens if navigate to a new page I have the global state in the client but I do something like this for a specific pages I want to add some information maybe I want to add some new fields
or maybe I want to initialize some data for a specific URLs. So in that situation I have a new state in the server defined for that page and then I have still some value in the client. What what's happening in this case? This is explaining the documentation
somewhere. If we go to API reference, I think it's um okay, I think it's better explained here.
Let me have a look at again here. Store client methods.
I think maybe it's in the interactivity router. Interactivity router. If we go to the package to the interactivity routter package.
No, this is not explained. This is something that um needs to be added to the documentation. So what's happening right now is that there is um soft merge happening right now.
There is a soft merge happening right now. which means that new properties will be added directly to the global state in the client but new
values for existing properties will not be merged. So we will have for the same properties we will have one value in the server and another value in the client. So how do we access the values coming from the state? So that's
why we have these methods available which are get server context, get server state. In this case it would be get server state. Get server state. Get server state.
We get server state. I can access I can access this and I can decide what to do. with these values.
So get server state retrieves the server state in an interactive region. This function serves the same purpose as get server context. We have a similar function for the context but it returns the state. The object returned is read only and includes the state defined in PHP with WBP interactivity state
which is this case. We have a default state defined in the server. But for a specific URLs I have some modified values. For example, extra data is different from the server for each URL. But then I have new fields happening
here. So when using actions navigate the object returned by get server state is updated to reflect the changes in its properties without affecting the state returned by star and we can subscribe to those changes to update the state if needed.
So if we start the navigation here the first time we can see how the state that comes from the server is completely merged with the properties that and the values we have defined for the state in the client. So we can make a difference between the state server and a state. But at the end that we can directly work with this.
But then we go to question one and we can see for example how the extra data property it has a different value than the one stored in the client state in the client global state. So here's where this function
comes handy. this one get server state because with get server state we can access the new values and decide what to do with them. Maybe I want to update this property with the new value or maybe I don't but I can decide to do that manually. In the case of the new fields they are automatically added to the state because they are not affecting anything.
So this this is how it works. This um Okay, I'm going to put this here.
Okay, nice. So, let's work a little bit on this uh project. Let's go through the logic. For example, one thing that I want to solve,
maybe I want to create I want to create a template. Let me see if I'm able to create a template custom template. So if we go to the editor
and we go to templates right now we are using the single post. So what I want to do is to
okay one maybe I'm not stealing WordPress 6.9. Yes I'm in WordPress 6.9. Okay. So, I thought there was a way to duplicate templates. Edit single posts.
Can I create? Okay, let me see. If I go to the post to the quiz post the template is single post. Um
create new template uh custom with template. Okay. Group content. Mhm. Okay. I'm going to try just this to see
what happens. This is the custom quiz template. And I want to create a page that I'm going to call with contest.
And this page I wanted to use the custom quiz template. Okay. And if I go to the page, I have nothing because
I need to edit the page. And I'm going to edit the page with the content of the quiz. So I'm going to copy this and I'm going to go to the page with contest.
And I'm going to put this here. So whenever I go to the page, I have this. So no WordPress, no header, no footer. The thing is that if I go here, let's see what happens. I think it's not going to work well, but okay. It worked well.
Nice. Then have this here. And if I go to quiz context, maybe I can just uh in the dashboard
in the settings general. Um, how do I define in the site editor that I want this page as a front page?
It should be somewhere here. Customize homepage settings. static page with context publish. Nice. So whenever I go here I'm going to log out.
Whenever I go to the homepage, I have this application. I have can go to question two. I go to question three
and I can reset the quiz. Nice. I like that. It feels like a like a page done with any other framework. Okay. One thing that I want to do is
that when the time gets to zero, okay, times up. That's fine. But I want to exclude the first page for that because by default this is zero, I think. And I want to solve that.
I haven't found a way. This should be simple, but I haven't found a way so far to do that. This is the portion of HTML that is displaying that text which is dynamically created with a derived state called timer text.
and timer text should return empty string whenever the timer is less than zero. And that's why by default
By default the time limit the time limit is defined I haven't explained this the time limit going to close this this This. This.
And this. This. I'm going to go to WordPress studio, which is here. And I'm going to get the
password of the admin. So I can log here. It's admin and what I wanted to show is
yeah that for each post and for each question I'm using the same block and the blocks each block has an attribute you can see this in the code here there's an attribute defined called time limit and the edit function is providing
an inspector control area to allow the user to edit that value. So whenever I edit this value and I save for example this value for question four when I save it starts in 10.
This value is stored as an attribute for the block and and set quiz. And if I go to question four, the timer starts in 10.
Because in the render PHP, we are getting this value from the attributes of the block. We are setting the time limit. The time limit variable is used to define the context for each block.
Why the context? Because this is a value that makes sense only for each block. I don't really want to share that globally. So I think it makes sense to be part of the context and that's why I'm defining this here by using the DBP interactivity data BP context. So this time limit
every time I load a page. I can see how it's part of the data context of each block.
Nice. And if I go to question three, we can see how this changes and we can get this value.
So the state in the client is merged with the state that is provided by the server. there's a merge and um there's a soft merge in the case of navigation but because this property property
time limit let me see we go to the console reset quiz this. It's in the context. It's in the context. If I go to question one,
time limit 22 and time limit 22. Okay, this is interesting because the time limit that was in the in the context
the fault field. Okay, let me do one test. I want to do one test. So these properties instead of defining them as part of the state, I want to define them as part of the context.
H extra data now in the client. Well, let's see what happens with this. Let's see what happens with this. If I go to here
set quiz or just the Okay, I need to No, I'm doing this already. So in the building the quiz I should
have this as part of the context. Nice. And so current SL context extra data. Ah okay. No, I need to I need to do this here.
I create the array and then I add the extra properties. Let's see what happens here. Okay. What I want to check Is that now
why is this uh provide maybe it's cached something if I do a full reload. Okay, let's do the problem that I'm having is that I am defining this extra data.
Ah, okay. Ah, okay. Because this extra data and the full fields were defined for the state. Okay. Yeah, it works as as expected. Okay. Now is the context in the server. Default field, default value, default data, default value, default data, chain limit and so on. If I go to question one,
the context server provides this new value that is updated. did but the question one data is not
merged. This is something that I need to clarify. Clarify. Yeah. Why are some values being merged? So time limit
um because on every new navigation ah okay yeah I know why I know why because I'm in the viewjs I'm specifically updating the context. Yeah, that's why because if I don't do this,
if I don't do this, I guess I would get the previous value. CTX is not defined because somewhere here. Okay, let me Let me comment this. Let me comment this.
Okay. Question one 21 20. Um, no. What I can do here is console text and context instead of updating. Let's analyze this. Let's analyze this.
Okay, first load of the page. What we have here is context from the server. what I'm getting from the server because this is the first load all of this is automatically merged in the client and because in the client I don't have any specific context
define well the okay here it makes no sense okay it makes no sense because I have one context in the client for the first time. But then every time I rewrite, let me see if I go to question one.
So now I have the context from the server that contains the new time limit, the new field and extra data. But in the client the uh yeah so the previous context remains as you
can see the previous context remains here. So we have default field the fault value the full data the time limit remains. So if I start this in question one
there is no timer happening. Um, okay. Let's see what happens if I start the time limit instead of minus one to um I don't know maybe 20.
Let's analyze this. If I define the default, my expectation is that the timer continues with the same value even if I navigate to a new page. This is my expectation here. So, let's see if that's true.
I'm going to reset quiz time limit minus one. This is not correct. Okay. Because I have changed the build. I need to change this one. Okay. Fire reset
and let me ah yeah you can see 20 19. Okay. So this has been 11. Okay, let's analyze this.
The first time we had 20 and 20, but the second time ah we start from 20 all the time. We start from 20 all the time.
We start from 20 all the time because I'm not updating this, right? Okay, this uh this is a timer that is in the state, right? It says a timer that is in the state. So this is not really affecting this. And every time I start I okay every time I start the page I initialize that value
with what happens if I define this as part of the context. Um, let me see. A state timer.
Okay, I have the context here. So, I should be able to instead of setting a state timer, I should be able to do context timer. Context timer. Context timer. Context timer. Context timer. Okay, let's change all the instances of state timer with
cdtx timer which I have here. And then in the timer text, I need to do this. I need to do this. Yeah, because I have changed this automatically. Okay,
let's see what happens here. This is exploration time. 20 19 18 17 Oh, it gets okay. It gets
h because I'm doing h limit because I'm doing this. If I don't do this, I don't do this.
Okay, if I don't do this times up because yeah, I need this. Okay. Context server time limit. Change this to ctx time limit because I have in the context I have a time
limit. So I was initializing every time to the context in the server and now I'm initializing to the context in the client which makes sense. So, okay, now it should work. 18 17 16.
No, this is not working. This is not working. But this is a good way to to explore this and to to learn more a bit about this. So let's check what we have. We have local context which is the same than the one we get from here.
20 seconds. 20 seconds. If I go to question one, it starts in 20 seconds. Why? Because every time I navigate this is reset to this value but I thought ah
because it's a timer and now we have time limit. Okay. So let's h continue with our exploration. What I'm going to do is instead of so timer what is timer define it's in the server timer
is minus one. Okay. So, what I'm going to say is what I'm going to say is
if CDX timer is um different that minus one then get whatever you have in CTX timer. If not then get reset to the original
value. So here
reset quiz. Right now in the context uh because it's not CTX timer is state timer. So if state timer or maybe what I can do is
find this also in the context 20 seconds. If I go to question one 17. Yay. And if I go to question three,
9 seconds. Yay, we got it. Okay, so yeah, we have this context server which is the value of the
attribute that it changes on different pages. This is the default value of the attribute. This is the custom one that we have set via the spectral control and this is the custom value. Then we have the local the value in the client that it doesn't change
unless we update it manually. And then we have the timer. As you can see, we have set something like okay, if timer is different that minus one, set it to the time limit value. Then every time I change the page, I
update it to the previous value. So the timer just continues. So, I don't really need this because I guess I can just define this as um
a value that doesn't get properties from the server. So, this is just an exploration, but this I going to um minus one.
Okay, this is uh reset to 20 because here I want it to be minus one. So now what I want to do is times up. This gets gets reset to the time limit of this page
of this the block on this page. And this has a different value. Stick timer. Stick timer. Um, I think I need to reset the quiz.
Times up. Question one 22. I think the values are too similar. So, let me post question three. Yeah, because I was really in the quiz. So, I want to go to question three,
exit code editor. And here I want to to maybe saving. And if we go to the homepage,
if we go to the homepage and and we have here the vector Question one 22.
We can see that from the server we are getting for slack question one we are getting time limit 22 that is set to time limit. If we go to question two, we can see the time limit and this timer has been set. And the state here, the
local state is the one. Okay, let me see if we can. We go to question one. The state here target.
Okay, this is the value that is being updated. So now what I want to do is to remove this text whenever we are in the homepage. This is not working. I don't know why because state timer
is less than zero. So let's do some debug. If I go to sources, go to view and we go to here state timer. I reload the page. State timer
is minus one. So this returns empty. Now start timer is zero. Why is zero? Why is this hero timer minus one
when this is set to zero? Is there any zero here? Ah, state timer zero. So that's why. Okay, let me see.
Don't need to do so start new timer time limit. I was I just can't remove this.
Um yeah, it's uh triggering this every time I go through this variable because it gets updated every time a state timer is updated as well. So I'm just going to
reset quiz. I don't get that value because state quiz is minus one. But then on every question I can show the remaining time and what I want to display is that the time is up. Yep. But in the reset quiz, this shouldn't be
displayed. Nice. Nice. Nice. Let's do some more fine tuning. Post one.
Okay. So right now the content that I'm getting is directly what I want to do is well we can let's do one test. I can see how whatever I put here
is not retrieved by the root region because the root region is this area here. This is nice actually because with block bindings, what I could do is to create here a section to edit any internal information
via me meta data for this post. And that information is not going to be um displayed by by the let's check this. I have this and
I'm going to this side. Okay. Okay, I want question one happens. Okay, question one. Yeah, we can see how all the information that was outside of the region is not displayed here. So, I can actually do that.
And here I have interactive logs. So here I can do some interactive magic. For example, this is an image that uses the activity API for this light box effect.
Nice. So what I want to display now is I will just to display the the number of the question. The number of the question.
No, the see the the number or the name of the question. I can do that here in the render. Maybe I can one thing that I would like to do is to separate this maybe a different file and then include it.
Okay, that's something to explore for now. What I want to do is to this is the content and maybe we can do here an H2 and H2 with um data wp text current slack. Um
I'm going to create a derived state called title quest and in view.js I'm going to say
Don't I have the question text for example here? Uh I'm just doing item SL. Okay, let's create title question or question text.
No, title question is a good one. So in the context like let's see what information do I have in the context. If I go to question two. Yeah, because Okay, let's um
for now title question is going to be just this. And I'm going to like this for now. The question is going to be just an empty string. If I go to question two, let's see the
information that I have in the context. What I have is the current slack and in the state I have the slacks here. So with current
slack um well ideally this is something that um this is something that it would be great to implement to add some meta data for the post and including some information like the title and I don't something else maybe some documentation
to to know more about that but yeah I think that the the project I'm going to remove uh well what I can do what I can do is to get the slack from the current slack
from the context. So what I can do is to to a const CTX constant slack and we can do this or yeah let's do this for
Um,
Okay, so this is the current context that gets updated on every new page. Let me try something.
Um, no, this is correct because t state title question and title question.
I get access to the context which contains the the current slack because the current slack the current slack is providing is provided here
and in the view I'm just Then uh because maybe there's um slash of something is or maybe the directives is not is not correct is data bit text. No, it's correct. H2 H2
Let me see here what's happening. Um, let me see if I go to the build and to the render. The H2 is there.
Um, let me do else. Okay. So,
let's debuck this a little bit. What's happening here? Okay, I don't care about this. But in question two, in question four, uh this is not
Stay timer. Okay, this is not triggered.
uh because I need to access not get context but get server context and I can directly destructure this
Okay. So, I reset and if I go to question two, let's see what's happening here. Okay.
What is this luck from contact server? Okay, this quiz that's fine. But if I go to question three, why is quiz? Because get server context.
Get server context. Get server context. At this point, it should
ser context at this point. It should provide. Okay. If I watch Um server context.
Okay, let's get this
Okay. I don't understand this. Okay. Reset quiz. quiz because server context server context current slack is quiz if
I go to question one. Okay, the console still has not displayed. So at this point,
this So in the context server the Slack is
question one but this is not displayed yet. title question. Okay, I know what's going on. I need to do
the slack get server context. Okay, and I'm going to return for That's fine for now. But in the in it question, I get subscribed to the context server.
So what I'm going to do is cdx the slack. No. Put in the slack. Yes. CTX. Put on the slack. Ah, this is down here in start timer.
Okay. In that case, I don't need to do this because whenever the timer starts, well, this is not the best place to do this, but for now, whenever the timer starts, the
I know this is an internal the slug. So I can do this. I can do this contact server init question and I'm initializing this here.
And um okay. And now the Yeah. Yeah. I need to do this. I get subscribed to the local that is going to be
set two. Okay. three. And if I remove this okay and okay, perfect. So, this is what I wanted to get. And I think, guys, I'm going to stop here.
Um, yeah, I'm very happy with this demo. I may make it bigger with a better design and with more questions and maybe with meta data that I can add to the to the post. Maybe even create a custom post type for the questions. And
and yeah, this can be like a nice demo of the interactivity routter and something that works uh really well. I think it's pretty fast the way it works. We can also do a preload preetch. This is something that I want to investigate. So every time I go to a question um
it's already loaded. So this can also be implemented. So yeah I'm going to what I'm going to do is to prepare maybe 20 questions 30 questions with the meta data pointing to the specific documentation sites. It will display a selection of five with this behavior. Each question will have specific time to answer the question. It can have images,
uh code blocks and a lot of things. It will be a yes or no. And what else? Um and yeah, it will will have a prefetch. So the navigation is uh bigger and at the end you will get a result. Whenever all the questions as whenever all the questions have been solved
you can get a button here to check results. If I reset quiz, I do start question one have some time. But if I navigate before I can get the time I have spent on each question and by the end I can get a a result. Okay. Yeah, I like it. I like it. This is a good use case for this. Okay guys,
hope you have a great weekend and hope this session has been useful. Um, and yeah, see you next week or any other week. Okay, bye guys., Interactivity Router, YouTube, 01kb67zt02jsmbrw30gxahacw2.