A note on qual­ity

This is a draft” post. If you’re look­ing for an ex­pla­na­tion of what a draft post is do­ing on a pub­lished site, you can find one here.

In short, this post most likely does not meet my high stan­dards — at times, even base­line. It may not be com­plete, have spelling er­rors, etc. I have pub­lished it be­cause I think in some way, as in­signif­i­cant as it could be, you might find it re­source­ful.

JavaScript30 Series

I started fo­cus­ing much more keenly on ReactJS and JavaScript while I looked for a job. This post is a part of the se­ries ti­tled JavaScript 30’, which be­gan early October 2020.

A pro­logue be­fore I get to the core of this blog post…

Life has been keep­ing me su­per busy. There’s so much non-dev stuff hap­pen­ing. After day four, which was the 9th of October, 2020, I re­al­ized I could­n’t keep up with a daily blog for JavaScript30 — I was spend­ing up­wards of an hour, some­times two, just draft­ing and fin­ish­ing a blog post… and, for an ex­er­cise that would usu­ally fin­ish in less than 30 min­utes.

I’ve de­cided to more or less free­wheel this. The idea is to post once a week, but we’ll see how it goes even so. I may also not link to a lot of ed­u­ca­tional re­sources — you’re good at this kind of stuff, look­ing things up, aren’t you? The joy of writ­ing, an es­sen­tial in­gre­di­ent, goes amiss try­ing to chase per­fec­tion.

That said, here’s a quick re­cap of things that have hap­pened over the last ten-ish days.

JavaScript30

Array Cardio Day One

For the most part, this was stan­dard Array ma­nip­u­la­tion stuff: map, filter, and sort. But it also had an elu­sive reduce method — and I fi­nally made some sense of it.

Tyler ex­plains why re­duce is con­sid­ered a very flex­i­ble and pow­er­ful Array method:

Reduce is the most flex­i­ble be­cause it can re-im­ple­ment the other ar­ray meth­ods such as map, fil­ter, and join, etc. You would­n’t re­ally want to be­cause those are avail­able, but re-im­ple­ment­ing each us­ing re­duce could be a good prac­tice ex­er­cise.

Sounds like a good prac­tice ex­er­cise, and I am keen to see if we take it up af­ter the 30 ex­er­cises by Wes Bos are through.

Source code.

Flex Panel Gallery

Today’s JavaScript30 ex­er­cise was a nice lit­tle brush­ing up of old con­cepts. We used the transitionend event once again, and acted fur­ther based on a cer­tain event.propertyName.

The thing that we had to build was… well, let’s call it a nice lit­tle mar­ket­ing splash page… that might be rel­e­vant for some­one in the travel in­dus­try. That’s as best as I can ex­plain it! Have a look at the demo your­self, or peek at the source code.

Type Ahead / Autocomplete

This ex­er­cise was quite chal­leng­ing and dare I say, very open-ended. We were sup­posed to build a JavaScript pow­ered in­put field that would show sug­ges­tions based on user in­put, as well as high­light the match­ing in­put within the re­sults.

A search input with 'Bos' typed in, showing results in a column such as Boston, Greensboro, and more - with respective population count next to it.

As you might guess, there’s tons of op­ti­miza­tion and fea­tures you could add. A goal I have kept in mind through these ex­er­cises is to try and stick to the orig­i­nal goals as much as pos­si­ble - only some­times work­ing through ex­tra knowl­edge. Here is where I broke that rule!

I made use of what’s called DocumentFragment. Since I knew there would be heavy ad­di­tions to DOM, it makes sense to per­form those op­er­a­tions in a virtual” DOM, and then ap­pend it at once. Pertinent code from the source, and a re­pro­duc­tion a lit­tle fur­ther down of the same source code.

A quick quote from MDN (emphasis mine) re­gard­ing DocumentFragment:

A com­mon use for DocumentFragment is to cre­ate one, as­sem­ble a DOM sub­tree within it, then ap­pend or in­sert the frag­ment into the DOM us­ing Node in­ter­face meth­ods such as ap­pend­Child() or in­sert­Be­fore(). Doing this moves the frag­men­t’s nodes into the DOM, leav­ing be­hind an empty DocumentFragment. Because all of the nodes are in­serted into the doc­u­ment at once, only one re­flow and ren­der is trig­gered in­stead of po­ten­tially one for each node in­serted if they were in­serted sep­a­rately.

As I learned while writ­ing a blog post just about DocumentFragment, they op­ti­mize for re­flow far more than they do for DOM per­for­mance — in my lim­ited test­ing. Chromium-based browsers cer­tainly ben­e­fit by a good ~30% in terms of raw per­for­mance, but the dif­fer­ence in per­for­mance on Firefox was neg­li­gi­ble. Given that the web is 60-70% Chromium/Chrome, it’s worth know­ing a lit­tle ex­tra op­ti­miza­tion tip like this one.

// 1. Build a document fragment of suggestions
const dom = document.createDocumentFragment();
const suggestionsList = [];
suggestions.forEach((suggested) => {
const suggestionItem = document.createElement("li");

const placeName = document.createElement("span");
placeName.classList.add("name");
placeName.textContent = `${suggested.city}, ${suggested.state}`;

// Replace match with span.hl
const highlightedPlaceName = document.createElement("span");
highlightedPlaceName.classList.add("hl");
highlightedPlaceName.textContent = input;
placeName.innerHTML = placeName.innerHTML.replace(
new RegExp(input, "gi"),
highlightedPlaceName.outerHTML
);

const population = document.createElement("span");
population.classList.add("population");
population.innerHTML = formatPopulation(
suggested.population
);

suggestionItem.insertAdjacentHTML(
"beforeend",
placeName.outerHTML + population.outerHTML
);
suggestionsList.push(suggestionItem);

// 2. Clear current children from suggestions list
removeChildren(currentSuggestions);

// 3a. Add new suggestions
// This:
// suggestionsList.forEach((suggestion) => {
// dom.appendChild(suggestion);
// });
// ...is the same as:
dom.append(...suggestionsList);

// 3b. Append fragment to real DOM.
currentSuggestions.appendChild(dom);
});

A word of cau­tion: I’ve seen appendChild with a for loop works the fastest, whereas us­ing append with the spread op­er­a­tor is sig­nif­i­cantly slower.

Demo and source code avail­able as usual. 🙂

Array Cardio Day Two

Very easy work with some Array in­stance meth­ods, such as: some, every, find, findIndex. The last one also in­vovled re­mov­ing an el­e­ment from an ar­ray, where Wes de­tailed two ap­proaches. I had used his first ap­proach in­stinc­tively, but the sec­ond ap­proach is one that I should prob­a­bly reach for:

// The first approach, which mutates the original array.
oldArray.splice(index, 0)
// The second approach, that does not mutate the original array.
const newArrayWithDeletedElement = [
...oldArray.slice(0, index),
...oldArray.slice(index + 1)
]

Fun With HTML5 Canvas

Confession time: I’ve never worked with HTML5 can­vas be­fore.

Which is also why this ex­er­cise took me a bit longer, and it def­i­nitely felt like it had a lot of in­for­ma­tion packed in. In fact, I think I’ll need to re­turn to this a lot be­fore this be­comes sec­ond na­ture.

We built a fun draw­ing board:

A user has drawn 'Hello world' onto a canvas with a brush that automatically changes color and stroke width.

Okay, I swear us­ing it is more fun than what it looks like. Try it out!

Dev Tools Domination

I haven’t in­vested a lot of time into browser DevTools in the past. They’ve cer­tainly be­come so use­ful and pow­er­ful over the years. My most used tabs would prob­a­bly be ac­ces­si­bil­ity, con­sole, in­spec­tor, and net­work. I’ve re­cently tried to play with the per­for­mance tab a bit more, as well as the de­bug­ger.

The les­son was prob­a­bly a bit more of an ease-in than a full-blown course of it­self. We learned a bunch of meth­ods on console: dir, group, time, groupCollapsed, and how to print styled as well as in­ter­po­lated strings. We also looked at how to add break­points to DOM nodes (as op­posed to the JavaScript code).

Some pretty in­ter­est­ing stuff but I won­der how of­ten se­nior/​lead devs re­ally use these bunch.

Source code.

ReactJS

In all this time, I’ve fin­ished a to­tal of 13 episodes from React for Beginners and I’m quite sur­prised there was so much to learn from even a course tar­geted at be­gin­ners. I do think I’ll need a more in-depth course to re­ally get a hang of how React works.

Using refs.

I’ve never been big on refs; af­ter all, the of­fi­cial docs dis­cour­age it as much as pos­si­ble. Wes is de­lib­er­ately us­ing them any­way, with a fair warn­ing of course, and that is ac­tu­ally a good thing. How else would you get some ex­er­cise on them?

You sim­ply cre­ate a ref by us­ing a method on the React class:

otp = React.createRef();

Then, you ref­er­ence it in the DOM node:

<input type="number" ref={this.otp} />

When re­quired in a method, just use it:

doThings = () => {
const value = this.otp.current.value;
}

This is the method en­cour­aged in React 16.3 and up­wards. For prior ver­sions, call­back refs are avail­able.

How to write meth­ods that don’t need to be bound man­u­ally.

This will prob­a­bly a whole ar­ti­cle of its own some time in the fu­ture. I think I need to re-watch this les­son and do my own re­search all over again as well.

They say the best way to know if you un­der­stand some­thing is if you can ex­plain it to some­one else. I just failed that test af­ter spend­ing ~1 hour to try and write a lu­cid ex­pla­na­tion that ac­tu­ally makes sense. :)

As far as the syn­tax goes (which is usu­ally the sim­pler part), write it as a prop­erty of the class us­ing the ar­row func­tion syn­tax, not as a func­tion that’s within the scope of the class:

class Example {
iAmSimplyAFunctionInScope() {
console.log("Hello world!";)
}

iAmAProperty = () => {
console.log("Hello again world");
}
}

There’s classes, this, and ar­row func­tions in­volved here, at least. Back to the draw­ing board.

Routing.

One of the stan­dard pack­ages for client-side rout­ing in React is react-router-dom. So, that’s what we used.

There’s not a lot of fancy stuff go­ing on here: we spec­ify which com­po­nent to load for which URL, make an ex­cep­tion for the in­dex page (exact prop for /) and a fall­back com­po­nent when no URL matches.

We also change the browser his­tory by mu­tat­ing the his­tory prop pro­vided by react-router-dom:

this.props.history.push(`/store/${storeName}`);

This lets back/​for­ward but­tons work as ex­pected.