The Hard Parts of UI Development

Auto-Updating Views with setInterval

Will Sentance

Will Sentance

The Hard Parts of UI Development

Check out a free preview of the full The Hard Parts of UI Development course

The "Auto-Updating Views with setInterval" Lesson is part of the full, The Hard Parts of UI Development course featured in this preview video. Here's what you'd learn in this lesson:

Will continues the auto-updating view example. The setInterval method will repeatedly call the dataToView function allowing the UI to be automatically updated rather than requiring the function to be called manually.


Transcript from the "Auto-Updating Views with setInterval" Lesson

>> Will: Okay, so we now hit in line 17. Another tricky line really, and actually, to be fair, we didn't dwell on this last time. So we'll do it properly this time, which is setInterval to which, Wye, we're passing, what function definition in full?
>> Speaker 2: We're passing data to view.

>> Will: Yes, exactly, or at least a reference to its function definition in full. And then, an argument of how many milliseconds should this the interval between each execution of data view, or data view?
>> Speaker 2: 15 milliseconds.
>> Will: 15 milliseconds. This line here is a 1. We move out of this line immediately.

Because what does it do? It grabs a dataToView function, or at least a link back to it in JavaScript, just to be precise. And it is going to pass it to, in the web browser, our timer feature. Now, as I say, this one technically is implemented somewhere between the JavaScript engine, I understand, and outside of it in the browser as a whole.

But, for what we need to do, we know that it is certainly not blocking running code in JavaScript. Of that, we're sure. We're instead passing to it, set up an interval of every 15 milliseconds. You will pass back your callback on and add to the callback queue the dataToView function.

dataToView function, there it is. I don't know why did it so big, but there it is. Brilliant, and that is that line done, finished. I'm gonna just literally cross it out. Do not think we're inside of it. Please do not think it's sitting on the call stack, set to interval.

No, it's done. But every 15 milliseconds, including 15 milliseconds later, in other words, almost immediately, we are going to get what function passed to the callback queue? Wye.
>> Speaker 2: We'll call dataToView.
>> Will: Yeah, absolutely. I'm gonna continue to ask Wye this one so that every time I have to say data after you say data and everyone feels [LAUGH] uncomfortable.

So it sits in the queue there, dataToView. There it sits until we are sure that there's nothing else executing. Well, we know there was nothing else executing, because that's the last part of our global synchronous, that is, in order down the page, code. So dataToView can be added from the queue.

The event loop checks. Is there any more code? Nope. To run? Nope. Is there anything any function on the call stack? Nope. And so dataToView can be added dataToView can be added to the call stack, where the help of JavaScript will ensure that it is executed, is run.

It's gonna add the parens for us to execute it. I love that. I think that's really cool. And then that is going to pass, or that's going to add or take. Sorry, let me get that right. That's gonna pass the thread of execution into the dataToView, the dataToView, function's brand new, what, everybody?

>> Speaker 2: Execution context.
>> Will: That's right, exactly. That was actually quite mellow and perfect tone for the morning, honestly, and not mellow in a bad way, mellow in a wonderful way. All right, that's lovely. So into it we go. And this is our essentially initial run of it, taking our initial state, our initial data and using it before any user action that can change that state, data, content that will then run the dataToView function again at that point.

Into it we go, and what are we gonna do? Phil, can you help me out what we're doing inside of our dataToView function?
>> Phil: Yeah, we're gonna access our JS input accessor object.
>> Will: Right, there it is.
>> Phil: We're going to find the value setter property on that object and set it equal to the value of post.

>> Will: Which is?
>> Phil: Which currently is an empty string.
>> Will: Empty string. So we know that value will be setting the value of the associated linked, hidden property link DOM element, in input, sorry. And that is where we set the value, perfect. Done, and same in the next line, Phil?

>> Phil: We're gonna basically do the same thing. We're gonna access the JS Div Accessor object.
>> Will: Yeah.
>> Phil: We're going to use the text content setter property on that object and set it equal to post, which is also.
>> Will: Didn't do it yet, but yes, there it is.

>> Phil: An empty string.
>> Will: And that's going to do nothing, really, for what the user sees. Again, there was a time where you wouldn't even turn data into empty content on the page, because what's there to do? It's already got it on the page. But by defaulting to everything the user sees must be a manifestation of underlying data, we're even going to go ahead displaying blank data, because it is data.

It still state. It's still something that can be changed by the user based on their action. Every single thing that can be changed, we have to figure out a way to, quote, display it or not. A div not showing up, it's still presentation causing view. In that case, it's data causing no view.

But it's still dependent on the underlying data. Okay, perfect. Brilliant, I think that's it. So our initial dataToView call is finished. Al right, good, so dataToView is popped off the call stack. Or, no, purple not possible. dataToView is popped off the call stack. And it was already out of the callback queue.

Sorry people, as soon as it gets added to the call stack, it's out of here, but we always forget to remove it because, yeah. Okay, now the user's just sitting and enjoying the page. Honestly, to be fair, they're literally figuring out what is? They're probably going, there's an empty input field.

And so they're quite excited but they're curious, but they're nervous to write in there because obviously this user interface has been terribly designed. There's no preview text even, right. So they're puzzling for a bit, but at about one minute, they take action. User actions. At about one minute, they take action and they are going to start typing.

So we're not doing a click first here. I mean, they technically will click first, but we have no handler, so we can ignore it. And they'll start typing, and what are they going to type? Let's have John. They're gonna type "John" and "John" is going to show up in their input field that is to say this C++ list of elements is gonna have "John" in its value in the input C++ object immediately.

An event is sent that triggers this handleInput function from C++ to be added to our callback queue. And there it goes. Our handleInput function is added. There it is. There it is. No code is running. We're at one minute, so nothing's running. We've been waiting a while here.

So, event loop goes, we're good to go. Put me on the call stack and handleInput will appear on the call stack where our friend JavaScript is gonna go ahead and execute it. And create everybody together a brand new.
>> Speaker 2: Execution context,
>> Will: Execution context, beautiful. 2, we said there's two functions here, one is propagating our data across and runs every 15 milliseconds, but essentially all the time, and the other a bit like as we described earlier in a game, basically here every sixty times a second as far as the eye can see.

And then, pinpoint we have a function handleInput, that is going to run only when user takes action. And then we're going to grab, hopefully the data as a submission of change to data before instantaneously our converter displays the consequence of that change in actual view. Hopefully the only consequence is defined in our dataToview converter, I want everything in there.

Nothing that can affect what the user sees based on their action should be outside of my converter function. It makes things predictable, it means everything is traceable back to underlying state. It enables me to reason in terms of not complex exponential flows of individual paths a user can take in terms of their actions.

Remove something, add something, click that thing, that would happen, shoot, now that's gonna change that, so we can't allow. No, everything would depend on state which we can then analyze in any given data here, what will the output be? And all the user can do is change us to a different state, different type or different value here in JavaScript.

And off that, we know, because we designed it in our dataToview function, what will show up, we can be sure of it. These aren't truths, these are moves to make our lives easier, these aren't facts, these are tactics. That's Ian, shout out to Ian for making something that was bad already even worse.

>> Speaker 2: [LAUGH]
>> Will: I mean, my thing was bad, I get you.
>> Speaker 2: [LAUGH]
>> Will: But just remember, these aren't like truths. These aren't like, this is, as we talk about these, you might be like, I could do that a different way, absolutely. There are different ways you can do all these things.

These are like what has become the standard, if only because, it's probably got fewer trade-offs than others. And also, it's become a, yeah, Will go ahead.
>> Speaker 2: Motions not notions.
>> Will: Okay, no, right.
>> Speaker 2: [LAUGH]
>> Will: This is, I don't even know what that mean, motion, it doesn't even make sense at this point like, this is rhyming words at this point.

Okay, brand new decision context as was said. And here it is, it's opened, and into it we go, where we are going to? Help me out, Jon, as you are special named person here. Jon, what are we gonna do in line 11?
>> Jon: So, we are setting our post variable to jsInputs value property.

>> Will: Right, but we know that that value property is actually, is it a setter or a getter?
>> Jon: It's a getter, right?
>> Will: It's a getter, spot on, to get the value of what?
>> Jon: Input.
>> Will: Which is?
>> Jon: Which is Jon.
>> Will: Which is Jon, fab, exactly, which is Jon.

And that.
>> Will: Which is Jon, and that then, will be assigned to post as a JavaScript string, great. If our model we're doing his usual job then dataToView would now be, reorder executing every 15 milliseconds, it will be executing to update Jon, both here and here. Nothing displayed to the user is not dependent on the underlying state for more than like 14 milliseconds, before the change happens.

However, before we do that, we have a, I probably should have done will, shouldn't I? No, rather than Jon. Okay, we'll probably change that in a second. So, we have a conditional, people, which is assessing is our, post value will. Phil, is that post value will?
>> Speaker 6: No.

>> Will: No, it's not. It probably should be for the purposes of our diagramming to save us doing, unnecessary diagramming. So sorry, Jon, we have instead gonna have, that's fine. We're gonna have the users input be, will, which is going to do something quite different. The user types will and that shows up on the value here, and then that's our value string that's going to be, sorry, the return that's gonna be got off the input element, and that's going to be saved as a JavaScript string on post.

>> Will: What is our value of post in line 12 and our conditional Phil?
>> Phil: Yeah, it is.
>> Will: It is, so post is, Will is true, and so we're going to run what method or what access or object Phil?
>> Speaket 7: We're gonna run the remove method on the jsDiv accessor after.

Brilliant, that's exactly what we're gonna do, and technically, and this actually is a moment to introduce the fact that, we have attached and unattached elements on our C++ list, sorry, the DOM.
>> Will: We do not actually, because we still have a label and access an object in JavaScript memory, we don't actually delete this DOM C++ element.

Instead, it just gets removed from the list of displayed elements and becomes an unattached element down here. And that's okay, I mean, that is what it is.
>> Will: But, what's most significant here is, our Div has disappeared. The users view what they're seeing is being affected from somewhere other than our dataToview converter function.

We are in other words, having consequences for our data, sorry, for our users' experience, what they see, based on things that are not tracked in data, in memory. This is because it turns out even the containers, the boxes that are being displayed are themselves things that have underlying data associated with them, whether we wanna admit it or not.

Displaying or not displaying a box is data being changed, in this case, the data of true or false, is that box there or not? Is that container there or not? If we want our dataToview function to actually capture all pipe, all possible things that the user can change and what they see through it, we need to put our element creation and or in theory removal but already unlike, isn't it better to not create it every time.

Well we'll see, into a dataToview function with it turns out, even our elements existence or not is a result of, there is something the user is seeing and can change. And in any real application, if you are writing a message, or if you're posting a tweet and it shows up right below, that is a new div.

That is a new division on the page has a new element being added, that is a previously not there and now there. That is, the user is changing what they see. That is the user changing the content. And therefore, that is, by implication, the user changing data and view, and what they're seeing.

Actually, let's rerun dataToView. It's gonna rerun in a second, right? Let's do that. Let's have a, handleInput is finished executing, unless I've missed anything. Stop me if I have. And in a moment, dataToView is going to, in its usual loop, start executing because of setInterval. And so there it is.

dataToView, auto parens added via JavaScript, brand new what, everybody?
>> Speaker 2: Execution context.
>> Will: Help me out while I'm getting the pen to work. Brand new execution context. There it is. It's writing so nicely on my preview. There it is, beautiful, brand new execution context. Doesn't that look fantastic?

Into it we go. We are going to what? Ian, what are we gonna do in our first line of our dataToView conversion?
>> Ian: We're going to use the accessor object jsInput, and assign its value to post. But the value is actually going to be a method provided to us by the DOM that we can use in JavaScript-

>> Will: Beautiful.
>> Ian: To assign its value.
>> Will: And look what we're gonna do there, people. We're going to ensure the user only sees stuff that we got from data, because that makes our lives wonderfully easy. And so Will shows up. I don't need to puzzle about what's gonna be displayed.

It depends on my data, and it's what's described in my one place, my dataToView converter function. I read my next line, my dataToView converter function should work as expected. Okay, jsDiv, tell me what's happening here, Ian?
>> Ian: jsDiv accessor object for the div is getting its text content setter called-

>> Will: Yeah.
>> Ian: With a parameter of post.
>> Will: And it's going to?
>> Ian: It's not attached to the document, so we're not actually gonna see anything, right?
>> Will: But we're gonna add the string, Will. I'm happy, I'm not even getting an error. [LAUGH] I'm thrilled. And the user is so proud, I've managed to type in Will, maybe this is just a prank for me.

So I've typed in my name, I'm thrilled. And the preview div disappears.
>> Will: I get no error for it, and I've got no idea where to track down what's caused my, now, look, it's not the case that we couldn't fix this. We heard a suggestion immediately, like, wait, wait, wait, are you checking whether there's a div?

But immediately, wow, what a thing to have to do! I thank you to our friend online who kinda teed up, that before we try and display content we're gonna need to, in another place, do a conditional check on what's currently rendered on the page. Whether we can then add text to that element.

I'm not even sure how we're checking whether it's being displayed or not, but we are gonna do that in our dataToView. And that's only gonna be necessary if, we gotta check if, okay, I'm sort of stumbling around. It's not that it's impossible by any means, we can certainly fix this code very quickly.

It's whether at a thousand elements, is this the best way to have condition saying, if the DOM element's being removed, or not there, or unattached, sorry, then please don't try and set its text content. I've already had to deal with three different steps there of a user's journey.

And there's another path that you could take. Imagine if all I have to reason about is, what is the state of the universe? And the user can change that, but I don't really care what they change it from or to, I just care about what's the state of it.

And then off that display my content. What a leveling up of reasoning. Is it perfect? No, we're gonna see those trade offs off it. Is it at least restrictive and predictable? You bet it is. This is our source of truth. This is what determines what's gonna show up.

Not random other callback handler plus initial. Don't forget that even input and div being there in the first place, is a consequence of data. That is to say, there is input and div true, versus now input and div, sorry, div false input still true, right? Don't think that this being up here is, as long as it can be turned off, then there is state behind it.

There is true or false. So we just didn't realize that actually we started off with implicitly input and div true exist on the page. And then with this handler's run, we turned it off. We want to have every piece of view that can be changed. It must have corresponding data for it to be changed.

We want to make that data explicit. Including whether or not the container for our more obvious data, the text, is even there or not.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now