React Mental Models: Cutting Holes In HTML

Last Updated:

The mental model

hole comic 1

What is the comic above about?

It's my mental model 1 for building a UI with React:

  • Step 1: Write some HTML
  • Step 2: Cut some holes

Cutting holes???

Yup, I'd cut some holes so that we'll see what's behind, like so:

hole comic 2

In all seriousness, it's how I see it when I make the UI work -- making it dynamic and interactive.

Of course we cannot physically cut holes in our code. And it's not exactly how React works. But I find this mental model very useful especially if you are new to React.

Bear with me, let me explain.

An example

Let's start with the simplest React app possible. Let's say we want to display this emoji Kungfu Panda (well, if you squint):

๐Ÿ’ช๐Ÿผ๐Ÿ‘Š

In React, we'll write a component like this:

function App() {
  return <div>๐Ÿ’ช๐Ÿผ๐Ÿ‘Š</div>
}

It's a function that returns an HTML tag. I'll expand on this HTML tag topic in another post, but for now just remember: we can use all the standard HTML tags after this return. If we surround the HTML with some JavaScript stuff, we get a React component.

Make it dynamic

Of course this app doesn't do much (if you are willing to call it an app anyways). We should make it interactive, right? How about adding a few buttons to switch the character? We want Kungfu Monkey, Kungfu Tiger and maybe Kungfu Pig too (try it below!).

๐Ÿ’ช๐Ÿผ๐Ÿ‘Š

So far what we've built with the HTML tag is like the drawing on the cardboard. It'll stay the same forever. It doesn't change.

How would we change the character in the picture? We'd cut a hole on the cardboard like so:

function App() {
  return <div>๐Ÿ’ช{}๐Ÿ‘Š</div>
}

Again, squint. Doesn't that { } look like a hole?

We'll then ask that panda/monkey/tiger/pig to stick its head out of that hole.

function App() {
  const who = '๐Ÿผ'
  return <div>๐Ÿ’ช{who}๐Ÿ‘Š</div>
}

Now if we want Kungfu Tiger, we just need to change the value of who in the code above.

Next let's add in a button to allow the user to do that.

function App() {
  const who = '๐Ÿผ'
  return (
    <div>
      <div>๐Ÿ’ช{who}๐Ÿ‘Š</div>
      <button
        onClick={function () {
          // TODO change "who" to ๐Ÿฏ
        }}
      >
        Tiger
      </button>
    </div>
  )
}

How would we change the value of who?

You'd probably do it this way:

who = '๐Ÿฏ'

Unfortunately that doesn't work. In React, we need a special way to change the data:

function App() {
const [who, setWho] = React.useState('๐Ÿผ')
return ( <div> <div>๐Ÿ’ช{ who }๐Ÿ‘Š</div> <button onClick={ function() { setWho('๐Ÿฏ') } }>Tiger</button> </div>
)
}

I know, the first highlighted line might seem alien. What are we doing there? Why do we need []? It's actually equivalent to this:

const result = React.useState('๐Ÿผ')
const who = result[0]
const setWho = result[1]

The reason we write [who, setWho] is because we expect the result of React.useState('๐Ÿผ') to be an array 2.

So, we defined both who and setWho here. setWho is a function that we can call to change the value of who 3, as we did in onClick. setWho('๐Ÿฏ') can be read as "set the value of who to ๐Ÿฏ".

Back to the hole-on-cardboard analogy, this setWho chooses the person behind the cardboard.

setWho choose the person

BTW, as you might have noticed, we have React.useState in the code. We just used state in our component!

Separate data from UI

The hole-on-cardboard analogy tells us an important idea about React. There are two separate things:

  • the overall structure (which tends to be static),
  • and the data (which change from time to time).

When we want to change the UI, we almost always reach out to the data. We DO NOT directly access the UI elements (DOM nodes). Instead, we change the data and the UI elements update automatically.

This may sound strange at first, especially if you are already familiar with older tools such as jQuery. In jQuery, for example, to change the text in a div, we directly "grab" that div and set its content:

$('div#who').text('๐Ÿฏ')

In contrast, we change the data instead in React:

setWho('๐Ÿฏ')

See, in the line above, there's no mentioning of div or any other things about a DOM node. We just change the data. The div DOM element automatically updates because we've done some preparation elsewhere. We've cut a hole which reveals the data behind:

<div>๐Ÿ’ช{who}๐Ÿ‘Š</div>

There are many benefits of separating the data from the UI. But to avoid talking too much about "theories" in one shot, I'll cover it in a future post.

Recap

Alright! I hope you have remembered a few things:

  1. We'd write HTML to define the static structure of a UI
  2. To make the UI dynamic, we'd cut "holes" in this structure with {}, and put the data in it.
  3. We'd use a function such as setWho to change the data. It's like switching the person behind the cardboard. Typically we'd call the set function in an event handler such as onClick of a button. This makes the UI interactive.
  4. We just used React state!

Let me reiterate. React does not work by cutting holes in HTML. But this is a useful mental model when you are just getting started.

The important idea here is that we separate the data from the UI. We almost always work with the data instead of accessing the DOM nodes. We'll dive deeper and see more examples of this idea in the next post.

Quiz time!

It's time to flex your muscles (or at least Panda's)! Write a component to help Panda and his pupils:

Are you ready? Give it a try with this starter project.

When you are done, tweet the URL of your sandbox to win a surprise gift! Remember to save your file before copying the URL.

Got stuck? Here's the solution. Promise me, don't peek until you've tried your very best!

See you soon! ๐Ÿ‘Š

Footnotes


  1. This and the following posts will cover my mental models of working with React. This switch of focus is inspired by Dan Abramov's Just JavaScript. It's such an whimsical way to learn JavaScript. Whether you are experienced in JS or not, I highly recommend you to check it out!โ†ฉ
  2. This is array destructuring in ES6.โ†ฉ
  3. Strictly speaking, who is a constant whose value cannot be changed. What setWho does is to inform React to call the App function again with a new value for who. I'll cover this in a later post.โ†ฉ

Visits: 0
Discuss on Twitter

I hope you find this article useful!

One of my 2021 goals is to write more posts that are useful, interactive and entertaining. Want to receive early previews of future posts? Sign up below. No spam, unsubscribe anytime.