Skip to main content

React demystified: Understanding the concept of state

If you've clicked on this article link, I assume you have used React. Also, if you've done any decent React development in the recent past (after the class components were retired), the first thing that you would've learned is the useState hook.

info

You understand how to use the hook but do you understand the rationale behind its existence in the first place?

Let's try to understand just that.


The static site

If the primary use case of React websites was to define static websites, the ones from the early days of the web, we would have had no need for useState. We could just do something like:

export default function StaticSite() {
return (
<>
<h1>Some static header</h1>
<p>Some static content that will never change</p>
</>
)
}

But, the issue is that static sites were a thing of the 90s (or maybe even before that). Nowadays, we need to have all sorts of functionality like:

  • Responding to user button clicks
  • Responding to scroll events
  • Changing content on route change (in case of SPA)

In short, a UX library needs to be reactive. (Is that why it's called React? 🤔)


Reactivity

This is a common word that basically means -

How does the library ensure that the UX rendered on the browser accurately represent the underlying state of the application

For instance, if you are implementing a counter web app and the user has clicked the increment button, how does the library take care that the incremented value is displayed?

Reactivity in React

And that is exactly where useState comes into the picture.

But, before getting into that, let's take a small detour and understand how React works in the first place.


A quick detour

When we use React as a library to create web apps, this is how it works:

We write some React code that faithfully represents a user interface to be shown on the browser. There are some static parts to this and some dynamic parts. In the context of a counter, this is what it would look like:

export default function App() {
const [count, setCount] = useState(0);
return (
<main>
<h1>Counter app</h1>
<h2>{count}</h2>
<button onClick={() => setCount(count + 1)}>increment</button>
</main>
)
}

The JSX that is returned from inside of this function is what React uses to create React element. It then compares the generated tree with the version of React DOM and then renders the result if necessary. Watch this quick video if you need more clarity on this:


Basically this graphic below summarizes it well:

Rendering in React


Why useState?

With that context set, let us now explore what would happen if there was no useState.

This is what our code would look like:

export default function App() {
const count = 0
return (
<main>
<h1>Counter app</h1>
<h2>{count}</h2>
<button onClick={() => {count = count + 1}>increment</button>
</main>
)
}

While this is perfectly legal code, you will see that upon clicking the button, nothing happens. And that is because, we are just changing a normal variable, and not a state variable.

And that is the core concept of this article. In React, the UI that is generated and shown to the user is a function of the state.

UI as a function of state in React

And since not all variables used in the component are state variables, the useState hook helps us define those few special variables that form the state.

It tells React to recompute the state when any of those variables changes. And whenever the state variable changes, React knows what it's time for - A UI update (if required).

Hope you learned something new today. 🙌🏾 Cheers!