The Hard Parts of UI Development

Composable Code with Map and Spread

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 "Composable Code with Map and Spread" 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 begins diagramming a more flexible virtual DOM. The flexibility comes from the method, which iterates through the data returned from the createDOM function. Each element in the list is passed to the convert function to generate a DOM element.


Transcript from the "Composable Code with Map and Spread" Lesson

>> Speaker 1: All right, so here we go, with our new element flexible code, we're gonna be able to compose code.
>> Speaker 2: I've added one new element here.
>> Speaker 1: Do I need to mark that off?
>> Speaker 2: No, I do not.
>> Speaker 1: So we're gonna use map, we're then gonna replace the elements.

>> Speaker 2: Here we go, people, this is almost our last diagram.
>> Speaker 1: I shouldn't start saying that, two and a half hours before the end, when there's two and a half hours more diagrams, but it's getting there.
>> Speaker 2: We are now gonna be element flexible.
>> Speaker 1: It's gonna allow us to have multiple elements in different order.

>> Speaker 2: I can switch around elements here, I could have ten great jobs.
>> Speaker 1: I could have great job, Phil, followed by Div, great job Y, followed by Div, great job, Alexa, followed by Div, great job, Matric followed by Div, great job, Justice followed by Div, great job, John, followed by Div, great job, Ian, followed by Div, great job, Paul.

>> Speaker 2: There we go, well done.
>> Speaker 1: I can just list them out.
>> Speaker 2: And then they will all be converted into DOM elements via my map that's going to run convert on every one of them.
>> Speaker 1: Here we go, so let's get diagramming.
>> Speaker 2: This is gonna be a flexible virtual visual JavaScript DOM that manifests in our C++ elements and I'm gonna start with Phil.

>> Speaker 1: Well, gotta first do some diagramming, haven't I?
>> Speaker 2: So let me get everything set up here, we have our web page, there we go.
>> Speaker 1: There's our JavaScript runtime and our C++.
>> Speaker 2: Thank you, beautiful, and we know that immediately in our C++, we have a body element, that's the whole page there.

>> Speaker 1: Our layout and render engine ensures that everything transfers to the page.
>> Speaker 2: And now we have our JavaScript runtime, everyone wanna see my schema again?
>> Speaker 1: No, no [LAUGH].
>> Speaker 2: [LAUGH]
>> Speaker 1: All right, we're going to anyway, app.html.
>> Speaker 2: There it is, and it loads into our web browser.

>> Speaker 1: The HTML parser is going to interpret each line and add it to the C++ list of elements whose output will be actual pixels.
>> Speaker 2: And then we have our JavaScript runtime which is where we really do most of our work with our memory, there we go.
>> Speaker 1: So we also know we have timer out of here, there it is.

>> Speaker 2: Okay, so, I've now closed my HTML file.
>> Speaker 1: It technically still has a script tag that's loading up at JavaScript runtime but I've got my little triangle there pointing right now, because that file is now closed.
>> Speaker 2: Okay, so Phil, jump me in.
>> Speaker 1: What's the first thing that gets auto added to my JavaScript memory when it's executed, sorry, when the runtime is hosted by the web browser and not by node?

>> Speaker 2: We get the document DOM.
>> Speaker 1: Beautiful, perfect, and that is going to be linked through a hidden property to what?
>> Speaker 2: Our DOM.
>> Speaker 1: To our DOM, beautiful, a hidden link to it, there it is.
>> Speaker 2: And I tell you, I'm keeping that enthusiasm up for the same thing, so there it is.

>> Speaker 1: And we have, what methods we're gonna find useful and what property we're gonna find useful here?
>> Speaker 2: The createElements method, and the body getter.
>> Speaker 1: Getter setter property, beautiful.
>> Speaker 2: Shoot, I didn't mean to, yeah, that's perfect.
>> Speaker 1: Good, okay, now let's get storing our data.
>> Speaker 2: We are then gonna have our JavaScript manifestation of that data instantiated, put into our description that's still data generic between line four and six or whatever it is.

>> Speaker 1: And then we have our elems.
>> Speaker 2: This is because now when we are mapping, we are not gonna be generating jsInput from our first, element jsDiv from our sort of index one element, jsInput from our index zero element.
>> Speaker 1: We are gonna be generic and have all of our accessor objects added to an array as a result of mapping over the vDOM that is going to be assigned to elems.

>> Speaker 2: So elems is now instead of jsInfo, jsDiv, it's a generic list.
>> Speaker 1: It will be as big as the number of elements, or number of elements we've described in our vDOM, and here it's gonna be three.
>> Speaker 2: So yeah, let's start putting some stuff in memory, Phil, please.

>> Speaker 1: We're gonna declare a name variable and initialize it to an empty string.
>> Speaker 2: Great.
>> Speaker 1: We're gonna declare a vDOM variable and leave it uninitialized.
>> Speaker 2: Great.
>> Speaker 1: And same thing, declare an elems variable.
>> Speaker 2: Perfect, perfect, beautiful, and then some function definitions.
>> Speaker 1: One's just a simple handler.

>> Speaker 2: Yeah, we declare a create DOM function.
>> Speaker 1: I'll just do the handler there, handle.
>> Speaker 2: What's the next one, update DOM?
>> Speaker 1: Sorry, I forgot createDOM, sorry, sorry, createVDOM.
>> Speaker 2: Sorry, I got ahead of myself, thank you, sorry Phil, what's the first one there?
>> Speaker 1: Create, I can't see where we're at on the board.

>> Speaker 2: Is it VDOM or-
>> Speaker 1: VDOM, yeah, that was completely my fault.
>> Speaker 2: createVDOM, and then it's the next one, it's the handler, handle.
>> Speaker 1: And then what's the next one?
>> Speaker 2: Declare the update DOM.
>> Speaker 1: Update DOM, brilliant, update DOM.
>> Speaker 2: Declare the convert function.
>> Speaker 1: Yeah, so let's just go through these each.

>> Speaker 2: createVDOM, we've seen before.
>> Speaker 1: It's going to, I guess, to use a word I don't really understand, instantiate our arrays, I shouldn't say that, to use a word I definitely understand.
>> Speaker 2: We're gonna call createVDOM.
>> Speaker 1: When we do our, I guess, non-specific, data still generic, dynamic description of what's gonna end up, hopefully, on the DOM, still has its placeholders.

>> Speaker 2: That when we run createVDOM, will get filled in with whatever the latest data is, great.
>> Speaker 1: There's our handle function, which is gonna introduce something here.
>> Speaker 2: Thank goodness, because otherwise I'm sure you're all thinking, why are we doing this one again?
>> Speaker 1: I got it, I know how Matt works.

>> Speaker 2: Well, we're also gonna introduce the event object, because once we are no longer giving individual labels in JavaScript to our input element on the DOM.
>> Speaker 1: While we could technically figure out by DOM traversal which element it is that the user's inputted on, and therefore get the value of it.

>> Speaker 2: It might be easier to use the event object that gives us all the information about the user's action.
>> Speaker 1: That's the handle function.
>> Speaker 2: Then we've got our updateDOM function that runs the virtual JavaScript visual DOM creation.
>> Speaker 1: Then it's gonna hit each element with the converter.

>> Speaker 2: And then it's gonna add the converted elements to the page.
>> Speaker 1: Then we have our convert function that needs to do all our job of converting.
>> Speaker 2: I probably should really put that one above update DOM, right, just sort of a logical flow, doesn't really matter, but just for logical flow.

>> Speaker 1: Remember, by the way, people, you will notice that we sometimes, I don't think we're doing it here, but we will end up calling functions before they're defined.
>> Speaker 2: Because we use the function keyword, we get this hoisting notion that ensures that all function definitions in our code are available immediately wherever we end up calling them, even above where they're defined.

>> Speaker 1: It's a design tradition from JavaScript, it's up to somebody whether they use it.
>> Speaker 2: But in this case, we're not using it, but we might end up using it later on.
>> Speaker 1: And then our setInterval is gonna be called, which is gonna run our main data to view converter, update DOM on repeat every 15 milliseconds.

>> Speaker 2: Sorry, I want to flesh that out, back to you, Phil.
>> Speaker 1: I sound like I've finished up a great report on local news.
>> Speaker 2: [LAUGH]
>> Speaker 1: [LAUGH]
>> Speaker 2: Do you want me to pick up on the setInterval?
>> Speaker 1: Just declare convert.
>> Speaker 2: I've done that and then, yeah, setInterval, brilliant.

>> Speaker 1: So we are going to execute the setInterval function.
>> Speaker 2: Beautiful.
>> Speaker 1: And passing to it as its first argument, the updateDOM function definition.
>> Speaker 2: Perfect.
>> Speaker 1: And the number 15 to denote 15 milliseconds in between.
>> Speaker 2: Beautiful, we find out the rules of that, by the way, on MDN, or ChatGPT, or GitHub Copilot.

>> Speaker 1: And then that is going to pass updateDOM to our timer to set what, Phil?
>> Speaker 2: 15 milliseconds.
>> Speaker 1: Yeah, and the associated function that will be called back at that moment, the callback function is, remind me again, what?
>> Speaker 2: UpdateDOM.
>> Speaker 1: UpdateDOM, brilliant, I'm not missing anything, right?

>> Speaker 2: That line is now, I have, I've got my call stack here ready to go.
>> Speaker 1: Call stack, there it is.
>> Speaker 2: And callback queue, perfect.
>> Speaker 1: Great, this line is now done, finished.
>> Speaker 2: And now, Phil, what happens 15 milliseconds later?
>> Speaker 1: 15 milliseconds later, the updateDOM callback function-

>> Speaker 2: Yeah.
>> Speaker 1: Is going to be introduced to our callback queue.
>> Speaker 2: Yes.
>> Speaker 1: Which at that point, the event loop will allow it to be pushed to the top of the call stack.
>> Speaker 2: Beautiful, I'm just gonna put it straight there because, yes, exactly as you say.

>> Speaker 1: So updateDOM, do we add parens on it here?
>> Speaker 2: No.
>> Speaker 1: No, JavaScript is going to put the parens on for us, there they are.
>> Speaker 2: No, that's not it.
>> Speaker 1: [LAUGH]
>> Speaker 2: I think we're all getting tired, but we're all doing very, very well.
>> Speaker 1: No, no, no, well, yep, there we go,
>> Speaker 2: There it is, added, beautiful.

>> Speaker 1: And we are going to start, our thread of execution is going to float in at about 15 milliseconds and start executing updateDOM with a brand new, everybody, is it time to wake up, a brand new what?
>> Speaker 2: Execution context.
>> Speaker 1: Beautiful, thank you, everybody.
>> Speaker 2: And there it is, and its execution context is created at the behest of JavaScript.

>> Speaker 1: And let me just see, it's gonna do a bunch of stuff, so I'm gonna try make it as big as possible.
>> Speaker 2: Really no need to shrink it at all, here.
>> Speaker 1: Let's have it as big as possible because it is our main function.
>> Speaker 2: But before all of that, we need to work with our more flexible, visualDOM and virtualDOM here, and we're gonna run updateDOM.

>> Speaker 1: Alexa, into it we go, and we are going to, well, tell me, what's gonna happen?
>> Speaker 2: So first, we're gonna reassign vDOM-
>> Speaker 1: Yeah.
>> Speaker 2: To the result of invoking create vDOM.
>> Speaker 1: Brilliant, create vDOM, which we know is going to have as its output, yeah?
>> Speaker 2: An array.

>> Speaker 1: Array of 3, I think, is it?
>> Speaker 2: Yes.
>> Speaker 1: Sub-arrays, I'm just gonna draw them there like that, people, just so we can sort of see, but that's going to be stored into, as you said, what global constant?
>> Speaker 2: VDOM.
>> Speaker 1: VDOM, okay, here it is, and like before, it's gonna have, yeah, now three sub-arrays.

>> Speaker 2: And each of them describes, hopefully, a different element to be added to the C++ list of elements that will show up on the page.
>> Speaker 1: Brilliant, and now, what are those three with our data passed into them, or evaluated in them?
>> Speaker 2: Yes, the first one is first the string input.

>> Speaker 1: Yep.
>> Speaker 2: And then an empty string.
>> Speaker 1: Yep.
>> Speaker 2: And then the handle function definition.
>> Speaker 1: Handle function definition, the next one?
>> Speaker 2: The next one is the string div, the string hello, !.
>> Speaker 1: Beautiful, I didn't do it so well there, but yeah, and the next one?

>> Speaker 2: The string div and the string, great job.
>> Speaker 1: Beautiful, note, by the way, not sure that one depends on our data, but that's okay, we're describing in full what the user will see in one place, that's kind of amazing.
>> Speaker 2: Great, now, we hit line 13, and we've got our visual, our virtual, our JavaScript DOM, but I want to have them on the actual DOM, but I don't wanna think about it too much.

>> Speaker 1: And I wanna have it flexible to however many of these elements I have.
>> Speaker 2: And I wanna have it flexible to changing up their order.
>> Speaker 1: Well, that's what we have in line 13.
>> Speaker 2: So elems is going to be the return value, the output of calling on this list of elements vDOM, the built-in map function and passing it, the convert function definition.

>> Speaker 1: What's it do?
>> Speaker 2: It's going to hit the vDOM, each element one by one with convert.
>> Speaker 1: So the first time, it's going to hit vDOM position what, Alexa?
>> Speaker 2: 0.
>> Speaker 1: VDOM position 0, brilliant.
>> Speaker 2: VDOM position 0, brand new execution context for it, and into it we go.

>> Speaker 1: Let's at least do the first one, if we don't do any more.
>> Speaker 2: Note that the output of this will be added to, as map does, map inside of it creates, what's map inside of it create, Alexa?
>> Speaker 1: An array.
>> Speaker 2: An array, exactly, ready for each element to be added, really, the return value of each call to the function convert that was passed in and is gonna be called as many times as there are elements in the array.

>> Speaker 1: If you've been to higher-order functions hard parts, what was it called, convert copy array?
>> Speaker 2: And so yeah, anyway, whatever we called map before the big reveal.
>> Speaker 1: So into convert we go and our node parameter, Alexa, is?
>> Speaker 2: Yes, in our local memory that's going to have the value of the 0th element of our vDOM.

>> Speaker 1: There it is, there.
>> Speaker 2: Which is an array with input empty string and the handle function definition.
>> Speaker 1: So it's an array of input, empty string, and the handle function definition, beautiful, there it is.
>> Speaker 2: And now, what do we do inside of this and assign to elem?

>> Speaker 1: We are going to call the createElement method on the document object, to use that hidden link to access the DOM and create a new element of the type that is at the 0th index of our node local variable, which is the string input,
>> Speaker 2: Beautiful, and that's gonna create, as you say, an input element on our C++,
>> Speaker 1: List of elements, the DOM, there it is.

>> Speaker 2: Brilliant, excellent, and we can't pull that back into JavaScript, so instead JavaScript gives us an output to assign to elem as a local temporary label.
>> Speaker 1: It gives us what?
>> Speaker 2: A JavaScript object-
>> Speaker 1: Yeah.
>> Speaker 2: With that new input node on the DOM.
>> Speaker 1: Yep.
>> Speaker 2: And all of our getter-setter methods-

>> Speaker 1: You're doing brilliantly, yeah.
>> Speaker 2: Go with an input.
>> Speaker 1: Yeah, perfect, yeah, perfect.
>> Speaker 2: Link to exactly the input and all of our getter-setter properties, including, I guess, well, the ones we know we're gonna have access to.
>> Speaker 1: And they're added by JavaScript, based on, as you say, what the element is we're linking to in the DOM, in this case, an input And we're then going to use some of those text content we're not gonna actively use, I mean we are, we've hopefully written some conditional logic saying, if node position zero is of type input, please only use the value and the oninput setters.

>> Speaker 2: However, that's too much code for me to write on this and I was trying to save space so that we can fit it on and diagram more easily.
>> Speaker 1: So we know that it will not cause any harm assigning to textContent, the user's view will not change.

>> Speaker 2: So we'll just skip over line 19 and hit line 20 where we're going to use what setter here, Alexa.
>> Speaker 1: The value.
>> Speaker 2: Exactly to set-
>> Speaker 1: To set the value on the input node on the DOM to be what is at our node array at index one, which is an empty string.

>> Speaker 2: Perfect, we're drawing it from our pretty picture here describing the page.
>> Speaker 1: It's an empty string and that empty string gets added to the DOM element, and then what's the line we do next?
>> Speaker 2: Then we are going to use our oninput setter-
>> Speaker 1: Yep.
>> Speaker 2: To set an input handler on the DOM on that input node to be the function definition that we have next-

>> Speaker 1: That was node 1.
>> Speaker 2: This is node position 2, exactly, which is?
>> Speaker 1: And that's handle.
>> Speaker 2: Handle, exactly.
>> Speaker 1: And we're going through convert here, but we know that in practice if we built this in our code for ourselves, we're going through this function.
>> Speaker 2: We're just describing what we want here.

>> Speaker 1: It's all gonna show up, isn't that beautiful?
>> Speaker 2: Of course we're all suffering here.
>> Speaker 1: [LAUGH]
>> Speaker 2: Because I don't know, it's nice knowing what's going on I guess.
>> Speaker 1: And then finally, we've done all of our work, we still have our accessor object.
>> Speaker 2: It's gonna be pushed into this array here along with two more from our further runnings of convert.

>> Speaker 1: So the next running of convert with V DOM position 1, don't worry, we're not gonna do it, I don't think.
>> Speaker 2: V DOM position 1 is gonna be pushed in as a second accessor object, what's gonnna be on our DOM, it's div.
>> Speaker 1: And we can look here, and hello text.

>> Speaker 2: Content is gonna be hello.
>> Speaker 1: There it is.
>> Speaker 2: Exclamation mark.
>> Speaker 1: And then because it's, and that object is then pushed in here with its link, and now our third is pushed in.
>> Speaker 2: By the way, I drew the objects here before they're actually returned out.

>> Speaker 1: The third is from another run of convert, this time V DOM 2, and that goes in as the third element of the array.
>> Speaker 2: And that is going to have created also an associated corresponding div element with its own text which is the string.
>> Speaker 1: Great job.

>> Speaker 2: Exactly, and now this list of three accessor objects will be returned out of the map call into which global constant, Alexa?
>> Speaker 1: Elems.
>> Speaker 2: Elems, brilliant.
>> Speaker 1: There it is.
>> Speaker 2: And there it is.
>> Speaker 1: I'm gonna draw it as a big array with inside of it three objects, each with an associated DOM element, and each with a link, each with a, I'm just gonna draw them at the side here.

>> Speaker 2: It's a bit funny, I know, but each with a link, link, link to their respective,
>> Speaker 1: Corresponding DOM elements.
>> Speaker 2: And each with their pertinent setter and getter properties available.
>> Speaker 1: My goodness [LAUGH].
>> Speaker 2: And so, at this point I'm sure you're all.
>> Speaker 1: Well, when I say that, by the way, I'm just commiserating, [LAUGH] but also I know you're not.

>> Speaker 2: I know you're absolutely rearing to go which is fantastic, because we have now only one last thing to do.
>> Speaker 1: Alexa, if you can finish it off for me here.
>> Speaker 2: We have only one last thing to do.
>> Speaker 1: We finished our map, we have a visual DOM with all of our data carried through.

>> Speaker 2: It's flowed into our elems, which it has access for the corresponding online DOM elements.
>> Speaker 1: And now, these DOM elements ain't showing up yet.
>> Speaker 2: So what do we do in our last line of update DOM?
>> Speaker 1: We are going to use replaceChildren which is on the body, which is on our document object-

>> Speaker 2: Yeah.
>> Speaker 1: That links to the DOM.
>> Speaker 2: But look what we've got to do here.
>> Speaker 1: A little bit different.
>> Speaker 2: Yes, so we are going to spread all of our elements in elems-
>> Speaker 1: Yeah.
>> Speaker 2: Into our list of arguments.
>> Speaker 1: So that's going to take elems position 0, elems position 1, and elems position 2, and insert them one by one by one to be the replacement of body's current, which is none, children.

>> Speaker 2: Which means we can just move our array, our list, to include our children elements now.
>> Speaker 1: And what will show up on our page but, input with nothing, and what a lot of work for nothing.
>> Speaker 2: And with hello and a div with great job.
>> Speaker 1: Hey, displayed from content.

>> Speaker 2: Yes, well done to Alexa, awesome work from Alexa.
>> Speaker 1: [APPLAUSE]
>> Speaker 2: Exactly right.
>> Speaker 1: Fantastic work from Alexa.
>> Speaker 2: Our update DOM execution context closes off, good.
>> Speaker 1: Our update DOM function has converted our underlying data into a full representation in JavaScript instantiated with its actual data, in this case, quite boring an empty string for now, that then produces through mapping over that and running convert to convert each of these descriptions into actual DOM elements and associated accessor objects.

>> Speaker 2: We end up with, once they're appended to the body or replaced existing children through the spread of those elements, we end up with our full user interface directly mirroring, or mirroring is a weird word for it to suggest reflection, I guess, directly mapped from the JavaScript description in lines 4 through 6.

>> Speaker 1: And the data instantiated representation of that, data implemented representation of that in the DOM, yay.

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