Identifying stuff in React: keys and refs

Use links below to save image.

One of the defining features of React is that it has the ability to avoid re-rendering the entire DOM whenever an individual component has been changed. To accomplish this, React needs to be able to reliably and consistently identify each individual component so that when a component changes, React is then able to isolate and re-render only that specific component. It also needs to be able to identify exactly which components are firing handlers or onChange methods, and see them as unique from the others around them, even if they were all generated dynamically from some ever-changing array in the back end. The ‘id’ and ‘class’ attributes won’t get the job done here. Let’s talk about ‘key’ and ‘ref’.

key

Image result for matrix key maker

Many of us just know the key attribute as “that thing you’re supposed to give to components when you generate those components from an array of objects.” But what is that attribute actually, and why is it important to set it when we generate components from iteration?

So as we know, React always needs to be able to uniquely identify every component on the page. And, as it turns out, it uses the ‘key’ attribute to do exactly that. No key attribute, no identification of individual components. No identification of individual components, no Virtual DOM. No Virtual DOM, no React.

“But David” you say. “I write components without the key attribute all the time. Surely React still works without every single component in the app having a key attribute.”

Nope. Thing is, whether you define a value for the key attribute or not, React gives a key attribute to every single component in the app. And the way it does it is by index – i.e., it’s place in position among its siblings that are nested at the same level in the HTML. Now, though that works enough to get the app running, it’s far from ideal. Let’s say you generate a list of components from an array. You work hard to carefully configure and style everything so that it’s just perfect. Then someone unshifts an object onto the beginning of your array on the backend, and the index of every generated component goes up by one. That’s why, when you generate a bunch of components without key values, React throws a warning. It’s not because the components have no key attributes – it’s because they have those attributes, and they’re set equal to their indexes, which is fragile and code smelly.

Some people don’t know this and get rid of the warning by iterating through their collection of objects and generating components where they manually set the key equal to ‘index.’ As we now know, that does nothing but repeat what React already does by default. It’ll get rid of the warning, but the problem React is telling us about is still there, so setting keys equal to indexes like this is a recognized anti-pattern.  It’s recommended that you use an id or some other unique property of your objects to reliably distinguish your components from each other.

ref

Use links below to save image.

Refs are a way to store a reference to a React element or component returned by the render( ) function, and make them accessible elsewhere in the component.

First. a warning – if you run into any tutorials that set the ref attribute to a string value and access the DOM node later from this.refs, you’re running into an old version of refs, which has been deprecated in favor of what we’ll be discussing today.

Second, another warning – the recommended use cases for refs are narrow. If you find that you’re using refs to handle all of your events and make a lot of things happen in your code, there’s a problem and you’re no longer doing declarative programming. Overuse of ref kind of flies in the face of Reactive programming, but it’s a good option to have on the table, and is often referred to as an ‘escape hatch.’ The only uses of ref that are recommended by the official React docs are 1) accessing the DOM API, 2) integrating 3rd-party libraries that are designed to hook into the DOM, and 3) imperatively triggering animations.

Alright, enough moping about what refs can’t do. We’re not defined by our limitations and neither are refs!

Image result for tony robbins

Tony Robbins is refs.

Seeing how refs are great for accessing DOM nodes, here’s a good example of a use case for refs: Say a user makes a mistake filling out a form, and we need her to re-enter some of the fields. We don’t want her to have to hunt all around the page looking for said field, so we decide that after she hits submit we want to immediately focus on the field where the problem is, saving the user some stress.

To accomplish this, we’ll need to access an input element using ref. Now again, once we do that, we could easily start abusing that reference by making use of it all over our code. Instead we’ll just call the focus( ) method on it. Let’s get started with an input tag and give it a ref attribute:

Use links below to save image.

As we can see, ref gets set equal to a callback function. The callback takes, as it’s input the tag (i.e. the DOM node) itself. It then creates a property on the component class called myInput and sets it equal to the node with the ref attribute. this.myInput can now be used anywhere in the component to  access that input element, and this.myInput.value could be used to get it’s value. Again, we do not want to use this reference to power the basic functionality of our app – that’s better left to state. But for our little use case, calling this.myInput.focus() is an awesome idea, and a perfect use of ref. Alright refs!

So hey, we’ll get back into our CSS discussion next week, but I think I might start writing more about React in the future – keep an eye out for more posts like this down the line!

 

Contextualizing CSS. Pt 1.

Sometimes we get so caught up in the syntax and minutiae of a language that we start missing the forest for the trees.

Image result for trees header

I mean, don’t get me wrong, you’ve definitely got to understand the trees. But if you never take a breath and step back for a bit, you’re inevitably gonna end up in a quagmire of confusion, superstition and fear. So that’s what we’re gonna be fighting, starting today – we’re going to be getting some perspective about CSS. This post is geared towards newbie/mid-level devs, and assumes that you’ve been learning CSS for at least a month or two.

First thing:

CSS is big.

This is important to understand. It’s easy to underestimate the size, scope and difficulty of CSS when you first get started in development. I mean, it’s just presentation, right? It’s surface stuff! Though it’s easy to get this impression from CSS off the bat, you only have to scratch the surface a teeny bit to learn otherwise. You know those O’Reilly programming books? The ones with pencil drawings of animals on the front? The CSS one is over a thousand pages:

Image result for definitive guide to css thick

The thing is, there’s always new stuff being added to CSS – it changes and grows every year, and it goes deep.

So what are all these changes? A  lot of it is imitating the stuff that the most popular CSS preprocessors and frameworks do. For examples, variables and grid systems were developed outside of vanilla CSS, but are now a part of it. If a tool becomes super popular and enough people ask for it, it might get added into CSS native, and could even end up  spelling the death of the tool that was the inspiration for it. Many people think that with the proliferation of CSS Grid and Flexbox, Bootstrap’s days are numbered. Of course, not everything from preprocessors and frameworks will find a home in native CSS – picturing functions and loops in standard CSS is a stretch. But nesting? Hey, who knows?

Who decides all this stuff, anyway?

The CSS specification is maintained by the Wordwide Web Consortium – basically the council of elders who decide everything about the standards for the core technologies that are used on the web.

Image result for world wide web consortium logo

Also, 4-time winner of the “Most Crushingly Dull Logo” Webby Award

So the W3C defines a bunch of standard related to the web, f.x. what is and is not official HTML and CSS. The CSS part is done by a subsection on the W3C called the CSS Working Group.

Image result for css working group

Neeeeeeerds.

 These fine folks are the ones who actually decided what CSS is. There are representatives from all the big web companies – Apple, Google, Mozilla, etc. They pay around 50 grand a year to have a seat at the table. There are also folks who are part of the group due to their stature in the CSS world and their contributions to the language. People like Bert Bos, who worked on the language in its infancy, are part of the group. I don’t know if he has to pay the 50 grand. Probably not.

So we know now that CSS is being changed all the time. How exactly does that happen? Well, the first thing we have to talk about is this:

Image result for css3

CSS3. As you might know, this is the current version of CSS – it’s what all the major browsers are running. What you are less likely to know is that this is the last version of CSS that we’re ever going to see. The change was made in 1999, and there has been no discussion of a new version. The reason why is that CSS is being broken up into modules, which are being improved independently of each other. And the different versions of these modules are not called versions, they are called levels. To get a look at the current state of affairs for all of these modules, take a look at the CSS Working Group ‘current work’ page.

Once the CSS Working Group makes a decision about something, the browsers have the responsibility to start adopting the new rules and conforming to the specification. They generally all do this pretty quickly, except for Internet Explorer. Everyone makes fun of them and you should feel free too, as well. You can see how a given CSS property is supported by different browsers at caniuse.com. Here’s an example of a support table for CSS Grid. This is very out of date, by the way – it’s way more supported by now:

Image result for caniuse grid

Wow, IE actually did pretty well this time around. How about that. 

Browser Schenanigans

One thing we need to touch on is the fact that browsers aren’t simply neutral middlemen that just render our code exactly the way the W3C says to in the spec. A bunch of the default CSS you are used to seeing when you write code is not part of the official CSS spec at all, but is rather defined by the browsers. By the way, browsers in this context are referred to as ‘user agents,’ and every user agent has a ‘User Agent Stylesheet.’ This refers to all the styles that the browser throws into our CSS on top of the definitions that the CSS Working Group lays out. These rules are things like making h1s bigger than h2s and putting confusing default margins on stuff. Here’s a piece of the Chrome User Agent Stylesheet:

chrome_uas

That screenshot comes via John Meiert’s awesome collection of User Agent Stylesheets. By and large, the styles the browser adds into our CSS at the very least kind of makes sense, and are useful for getting us thinking in terms of proper semantic HTML. But they can also kind of get in the way, and confuse us about where certain styles are coming from. As such, you may want to reach for a CSS reset. This is a big chunk of CSS that basically just resets everything to zero – turns off default margins, makes everything the same size, stops links from turning all blue and underlined and whatnot. You can write your own, of course, but grabbing one from someone’s blog is pretty darn convenient. Some resets are more drastic than others, google around until you find whatever you’re looking for. Here’s an example of what a piece of one might look like:

Image result for css reset

And that’s it for today! Next week we’ll talk about the wonderful world of CSS tools and extensions – preprocessors, frameworks, grid systems, you name it! Thanks for reading!