The Hard Parts of UI Development

Generating VDOM Elements from Array

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 "Generating VDOM Elements from Array" 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 refactors the createDOM function further by creating a Post function which generates DIV elements from an Array of posts. This technique is a more concise way to create multiple elements of a similar type.


Transcript from the "Generating VDOM Elements from Array" Lesson

>> Let's just look at a bit of a slightly more flexible even way of doing this, even more UI composition. Because a great point by which we'll come to in a second. Even more UI composition creating multiple, similar Virtual DOM elements each with different actual data. So if I wanted to have 50 Twitter posts and of course in practice it's got more information, it's got the number of likes whatever.

It can be very simple. If I have 50 Twitter posts, I do not want to really list them down in a giant array of arrays. So in practice, what I will do and what is done in all the frameworks is create a function like post here that when run with an individual piece of data will return out.

Not that profound another array element with div and the message is its content it's very profound. This is what a functional component is doing it is creating when run a piece of our visual representation of the page. So the only thing that has changed here is if you look at our input name handle, there it is.

I've now got rid of these two divs and I am now taking my post Ginger, Gez, Ursy, Fen my four sisters, that's their nicknames. There we go, yeah, that is all their nicknames Fen's got the most nicknames. But Ginger, Gez, Ursy, Fen and I am going to map over those individual names and insert each of those strings as the input to respectively zero index, one index, second index, third index is call to post.

So the first time I call post will pass in Ginger and return out div Ginger. Second time I call post I'll pass in Gez return out div Gez, third time div Ursy, fourth time div Fen. And then that will be and then I'm gonna have to spread them again because now that's an array of arrays and I actually just want a list of arrays.

I wanna have them like added to my, I don't wanna have input, name handle and then an array full of subarrays. I actually just want all of those arrays listed out. I could make this work to have that be a collection of arrays. And that's where, if you go to the challenges which I really look forward to getting a chance to do as well myself and I hope you all get a chance to do.

We can start to build these out to handle, sub elements, clusters of elements, child elements all using a recursive call to our convert function. That ensures that if it finds an array of arrays, it will step in and loop through all of those to create elements. Or if we have our contents, which is our position 1 of a given node here, Li, Hello, Li and great job.

What if we could have in there our contents actually be three, four, five, 50 other nodes? Then we could write conditional logic that says, if you find that node position one in the virtual DOM is an array rather than a piece of text. Don't try and display the array jump in and run through and produce all of its elements on the DOM itself.

But those are in the challenges let's actually show this a little bit here. And one other fun thing here is if you look at handle now rather than updating a name value it's pushing each letter to be fair cuz I didn't wanna have it handleInputs and then an enter.

But each letter that we write, it will add to our list of posts and because our data directly manifests in our VDOM because of our update DOM running on a loop. We will get automatically all of those messages as soon as a post is pushed, as soon as the value of an input, sorry, value of an input yeah to the input field is pushed to posts.

Immediately, we will get a redisplay, a re-render of our entire list of post. If I were to write will, I would get my post would be now Ginger, Gez, Ursy, Fed Will. And ideally, we'd have a better input handler than that that only a pen superimposed upon, let's say the content being above three letters long or on user pressing Enter or whatever it might be but too much code.

So then the createVDOM call inside of our repeatedly running updateDOM would take our now longer list and map over it. Create post elements, div and the underlying the message for one for w, for i, for l and for l. Let's just draw this for a little second, not go into it in full.

But let's just draw this for a little second here because right after this we're going to have to talk performance because this is untenable, no doubt about that. So looking at our posts, so there's gonna be a little bit scrappy here but looking at our posts where we have Ginger, Gez, Ursy and Fen.

There it is, we would now if you look inside the called createVDOM that we did here that produced our array of arrays. We would have our input and whoops! Oh, whoops. [INAUDIBLE] That's a wonderful error. I don't see any name defined, make no comment. Yet, there'll be our input and our name, no comment on that.

And then immediately after, we would map over posts and we will run our post element creation function post with our first value of our posts array which is what? Why?
>> Ginger.
>> Ginger [LAUGH] that's right so funny using my sister's name for this. There it is and into it we go and I guess we could show our execution context here and our message parameter would evaluate to what why

>> Same thing the string Ginger
>> Ginger and then we would create an array with string div and string Ginger. I say a div, that's why you start to almost verbally call these even though in reality it's actually just an array. And we would return that out. We're sorry, we're gonna make sure it's not confusing here.

We will return that out and then we will do, post again with Gez. Get another one post again with Ursy. Get another one post again with Fen and we would have an array of arrays; four of them. But we wouldn't want to have the array of arrays, we would want to just grab the four arrays to put into our VDOM directly.

So we would spread the resultant array of arrays leaving us just with these four in our VDOM and then we're good to go. And then as I say, as the user starts typing in response to the input into the input field we would rather than append to the string that's typed, replace our value of name, we'd have a defined name globally, so no comment in line seven.

We would instead push that thing that the user typed, albeit letter by letter but we're just trying to keep it simple here into posts. And now as we then hit our rerun of updateDOM to change what's displayed as well based on the data instantly our post would now have five elements including the new thing type and would directly mirror our underlying data.

Even more composition, the ability to describe in our code little units of code that we can reuse and move around and end up displaying, as we hope, visually in our JavaScript, visually on our page. So even more composition, creating multiple similar VDOM elements each with different data. We can produce our VDOM elements, virtual visual DOM elements with a function so we can then easily add new elements to our list.

In this case, post defines a dataToview relationship with a data. Each element in the array post, there it was changes for each of the posts because we're going to map over. Boom, boom, boom, boom add more elements, boom, grab it, no problem. Add more tweets that's what happens when you type a tweet and press Enter and it appears, we've added to an underlying list.

And now we are upon the mapping over that list of data, producing all the corresponding elements on the DOM and replacing the existing ones. In theory, we may want to be more optimal on that we'll see that in a moment. We can even add more logic to the post function here.

You can see I initially redid the input one as a function as well. So I could also have created input as I actually would in practice as a function producing the input jsDOM VDOM element, the array from a function as well. That becomes a standard approach. In fact, if you look at something like React they wrap up that array creation and technically had create an object.

They wrap that up or they they wrap that up in a create element function call, that they wrap up in JSX. So the JSX that you see when you create an element or you have a class or a function, creating an element is under the hood running a create element function that produces technically an object.

But just like an array like this describing what's going to be displayed. They then create an syntactic sugar layer on top called JSX that looks actually like the thing they end up creating. Well, it looks more like yeah once you get into framework implementation you can see why it's so satisfying to model these up out from the ground up because now it's like, okay, that's what you can see.

We can see what a React Component under the hood is doing here can add even more logic to that post function to make it more powerful. So I could totally have inside that post function now, not just create each of my what each quarter it creates an element div and Ginger that's then creates a DOM element via the conversion of each of those elements.

Inside update Dom in line 14, I could also have that post function just to add the logic in it. It could determine whether to add a particular class or whether to display those messages in some particular way or whether to only add so many messages. But there's all sorts of things we could do determining what ends up being returned out for the actual view as described in that post function.

Because it is now the description in createVDOM call of the relationship between the underlying data and what's being displayed. It's just being contained within a function but it is still in createVDOM describing the relationship between the data. And well, with the data here and the step two the JavaScript representation of it before we hit step three the conversion to actual DOM elements which displays on the actual page.

All right, let's have thumbs though on this now more composable. I would be very interested to hear some clarification questions on this, okay. Paul's got a clarification, hooray! Paul, go ahead.
>> Just a quick question, on your function post you have it capitalized is there a reason why it's capitalized?

>> Great question, Paul. That's one of those questions that's so thoughtfully teeing up. Yeah, because it becomes a standard in UI frameworks that when a function is acting as a description of a relationship between underlying data. In this case, it's our list of messages and how it should be displayed.

In this case, it's got a description, it's gonna be a div with that message as the content that is known as a UI component. In this case, we have no handlers on it. We have no it's very, very, very minimal. And really, probably I should have well no nowhere else have I got a function that describes that relationship.

I guess creating the DOM does but it's doing everything. If I had more, if I've created input element there in line seven also with a function which I could have done. Function, input I'd have done an uppercase, return that array. That's a convention within UI framework design that whenever it is a UI component, describing that relationship between underlying data and what's displayed.

Use an uppercase for the first letter and that's a convention. That's why I did it here I guess to sort of show hey we've reached a full component here just being used in part of our application. Great question Paul.

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