Refactoring with let Block Scope

While I was refactoring a code challenge today, I learned something very cool about ES6 variable declarations via the let keyword vs. variable declarations via the var keyword. let is scoped to the nearest block while var is scoped to the nearest function. This is particularly important in the context of loops because let will create a new binding of a variable for each iteration; var will only create one binding.

When you have a callback inside a loop that relies on separate bindings at each step, using let saves you the headache of wrapping the callback in a closure to make copies of the variable at each increment. The canonical example is calling JavaScript’s setTimeout() function inside a loop to execute a function or code snippet after a specified period of time (delay) in milliseconds:

Let’s take a look at how this informed the refactoring of my code.

I was tasked with building a tool that takes a sequence of CSS styles as input and uses vanilla JavaScript to apply each step in the sequence to the DOM, animating an element over time.

The input consists of a 2D array of CSS styles, where each array has a time delay and any number of style objects.

To implement the animator, I looped over the input and set timers to update the style of an element in the DOM after a delay. let‘s block scope binding allowed me to refactor my code without a closure.

An integral part of the challenge is that each step is relative to the previous step. So it’s not enough to apply the styles at step 2 after 200 milliseconds (see input array above); step 2 must be applied after delay + delaySoFar milliseconds, or 300 milliseconds. Likewise, step 3 must be applied after 500 milliseconds.

To persist the cumulative delay, on line 29 above, I declare the variable delaySoFar outside of the loop. Inside of the loop, I set each step’s delay to the sum of the current delay (sequence[0]) and delaySoFarOn line 36, I invoke setTimeOut(), without a closure thanks to let‘s block scope binding. Inside each timer, I set the style of an element in the DOM after the current delay. Last, after the timer is set but before the next loop, I update delaySoFar. The result animates the element and each step’s delay is relative to the previous step.

I really enjoyed this code challenge. The efficiency of let‘s block scoping is nifty.

Some More Thoughts on React

I’ve been immersed in React for about three weeks now, and so far I’m finding it really easy to organize and maintain. Compared to Angular 1 (still haven’t tried Angular 2), my code is also much easier to read and understand. I like how JSX lets me embed HTML-like syntax inside JavaScript, instead of having separate HTML templates with Angular’s unique syntax embedded within. With React, you don’t have to learn all that new syntax.

An all-JavaScript approach not only feels intuitive but it has performance benefits. React achieves this by decoupling state from the DOM and storing it in a virtual DOM. When state lives in the real DOM you must traverse a sometimes huge tree structure to update a node (think jQuery), whereas with React’s virtual DOM, it keeps an eye on the state of a component via a diff algorithm, and whenever it changes, it simply converts the component to a React element and inserts it in the DOM. Imagine a DOM with thousands of child nodes – the virtual DOM approach results in far greater efficiency.

Furthermore, the idea of designing a code base in terms of reusable UI components instead of a larger MVC framework vis-a-vis Angular 1, cuts down significantly on my code base. Its principles encourage me to think more about the features and layout of my site.

Most important, I love the React environment. With webpack and the webpack-dev-server, debugging is a synch because it happens in real time; the server watches your source files and recompiles them whenever there is a change. If there’s a bug, the app will break and almost always yield a helpful error message because React is all JavaScript. On the other hand, because Angular embeds its own syntax in HTML templates, debugging can be more difficult.

I also love the object-oriented approach that React encourages. With ES6 classes, I can define state and the events that change it in the constructor of my component. That makes the code more succinct and maintainable for a colleague who might jump in on a project. Here’s an example of an ES6 class with a constructor function from a current project I’m working on:

Lines 7-9 above demonstrate how quickly one can get up to speed on what this component is responsible for: keeping track of a username in the DOM. Line 7 signifies that the username property is what we are watching. Line 8 tells us that there is an event that updates that property while line 9 shows there is a form submission event. A fellow developer jumping into this code would be off to a great start synthesizing its purpose. On a side note, it’s important to note that we must call .bind and pass in this on both of our events; otherwise this will be undefined in the method.

Let’s talk about line 5 as well. All React classes are initialized with a props object via calling super(props). Don’t be sidetracked by the super part. The only effect of calling super on props is so you can access this in the constructor. It’s probably redundant because we already have reference to props but the React docs encourage it: “Class components should always call the base constructor with props,” which is in keeping with object-oriented JavaScript’s standard of binding instance properties to this.

The props object allows you to access anything you pass in while “invoking” a component. Because I’m using React Router, my props object contains all sorts of useful information like routes, route params, and location, plus anything else I want to pass when I invoke the component.

Let’s take a look at my routes and compare it with the props object it yields.

On line 11, I “invoke” a route component and pass it three key/value params: path=’playerOne’, header=’Player One’, and component={PromptContainer}. component points to the class where all this information is headed.

Now, inside the constructor of PromptContainer, let’s log the props object to the console. A lot of useful information lives in props when you use React Router, but lets focus on what we manually passed in. The route object contains all the info we passed in and we can now access by call any of the keys on this.props.route.

screen-shot-2017-01-13-at-11-19-08-am

Finally, let’s demonstrate how we can use props, state, and the events defined in our constructor in the render method of our UI component:

On line 3, we access our header prop as the value of our tag. Line 5, binds the onSubmitUser event to the React onSubmit callback. Line 11 binds our onUpdateUser event to React’s onChange event (this watches for any changes to the input field). Last, on line 12 we set the initial value of the input field to the state of username defined in the constructor.

Check out this codepen to see a working example. Note that the app is incomplete. After you enter player two’s name, an alert will flash.

Functional React Components and Props

In this post, I’ll show how to build an avatar using functional React components. You can think of React components as isolated building blocks to reuse throughout an application. They accept inputs and return elements for updating the DOM.

Functional React components are pure. Just like pure functions in JavaScript their execution doesn’t depend on the state of the application, they don’t modify any variables outside their scope (no side effects!), and they always return the same result given the same arguments. Because of React’s adherence to pure components, learning React makes you a better developer. It also makes testing easier.

To start our avatar component, let’s think about what building blocks we’ll need to make it. An avatar has a user image, a user name and a probably a link to a user profile. Hmm, sounds like we need a user object. We’ll define one using an ES6 constant, call ReactDOM’s render method and pass it our forthcoming Avatar component.

ReactDOM’s render method takes two arguments — our avatar component that returns a UI object and the element in the DOM where the UI will be updated to. As we “invoke” the Avatar component we pass it the user as props, essentially parameters the component will use to create the UI. Now we can define an Avatar function and access the user object.

Our Avatar component is comprised of three other components: ProfilePic, ProfileName and ProfileLink. Each needs access to some part of our user object. As we “invoke” the child components, we pass in the necessary props. It’s important to note that the React component rendered in the DOM must be wrapped in a div.

With our child components we don’t need to worry about a container. Each child component can just return whatever element it needs to. And that’s pretty much all there is to building function react components. Nothing too fancy — it’s very similar to writing pure functions with JavaScript. The only difference is we’re returning JSX instead of primitive values.

Checkout the example on CodePen.