Rendering Lists and the Event API
How to use JavaScript's map, spread syntax, and the Event API to make a Virtual DOM scalable for handling lists.
In the previous module, we took a huge architectural leap. We started describing our UI visually as an array of arrays in JavaScript--our Virtual DOM. We then used a generic convert function to translate that visual representation into real document.createElement commands under the hood.
However, the way we passed those elements to the DOM was not scalable:
// Very rigid
let jsInput = convert(vDOM[0]);
let jsDiv = convert(vDOM[1]);
document.body.replaceChildren(jsInput, jsDiv);If we have 50 items (like tweets or posts), we cannot manually index vDOM[0] through vDOM[49]. We need a way to dynamically handle however many elements happen to exist in our Virtual DOM based on our underlying data.
Mapping the Virtual DOM
Fortunately, since our Virtual DOM is essentially just a JavaScript array, we can fall back on JavaScript's standard list-processing functions. Specifically: map.
let elems = vDOM.map(convert);By calling map, JavaScript will pass every element inside our vDOM array through our convert function. The output of map is a brand new array (elems), filled with the actual linked DOM/accessor objects that convert returns.
This makes our component logic flexible. If the underlying data dictates that vDOM should have 5 items today and 500 items tomorrow, the single .map(convert) line handles it. We no longer care how many items are in the structure.
The Spread Operator
There is one small problem. The document.body.replaceChildren() method does not accept an array. It expects a comma-separated list of individual arguments.
// This breaks: replaceChildren doesn't take an array
document.body.replaceChildren(elems);
// This works, but we don't know how many elements there are
document.body.replaceChildren(elems[0], elems[1], elems[2]);To bridge this gap, we use the JavaScript spread syntax (...). Spread takes an iterable, like an array, and "spreads" it out into individual arguments.
document.body.replaceChildren(...elems);When JavaScript runs this code, it essentially unpacks the elems array right inside the function parentheses, placing each item natively beside the others.
ExpandMapping virtual elements into spread parameters
The Event API
We have made our view generation flexible, but our input handling now has a problem.
Previously, we used a specific jsInput variable globally so our input handler knew exactly where to grab the user's text from: post = jsInput.value;.
But if we are generating loops of anonymous elements via map, how does our handler function know which element the user typed into? We can no longer hardcode a global variable reference.
Enter the Event API.
When the browser detects a user action (a click, a keystroke), it adds the corresponding handler function to the callback queue. But it doesn't just call the function empty-handed. The browser automatically generates an Event Object full of rich details about the action--and passes it into our handler as the first argument.
function handleInput(e) {
// e is the auto-inserted Event Object
post = e.target.value;
}By catching that object via the parameter e, we unlock immense power. We can check the exact cursor coordinates (e.clientX), or whether the shift key was held (e.shiftKey).
Most importantly, we get access to e.target. This is a direct reference to the specific DOM element that triggered the event.
By using e.target.value, our handler becomes completely generic. It simply reaches into the exact element the user touched, grabs the value, and updates the data. We no longer need to manually wire specific variables between our view creation logic and our event handlers. The event object bridges the gap perfectly.
With flexible list processing and target-aware events, we have laid the groundwork. We are now ready to tackle the holy grail of modern UI development: assembling these generic pieces into Reusable Functional Components.
Further Reading and Watching
- Video: JavaScript Event Object Explained -- Bro Code
- Article / Docs: Event reference (MDN)
Keep reading