State in React

Author
By Darío Rivera
Posted On in React

In previous articles, we explored React components and props. Now we will introduce one of the most important concepts in React: state. State allows components to store and update data over time. When state changes, React automatically re-renders the component.

What Is State?

State is data that belongs to a component and can change over time. The useState hook is a built-in function in React that allows you to add state (component-specific memory) to functional components.

We need to use the useState hook for two principal reasons:

- Local variables don’t persist between renders: Trying to use local variables to track the state doesn't work as they are not considered when React re-render components.
- Changes to local variables won’t trigger renders: Whenever a local variable changes, it won't update the interface as React doesn't notice it.

Let's check the following Counter application to take a look at how the state is used in React.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

export default Counter;

Notice the use of the following destructuring assignment:

const [count, setCount] = useState(0);

It basically assigns count=0. Passing a parameter to useState assigns an initial value to the state. Every modification to the state (i.e count) will require executing the setCount function. There is no rule to name these identifiers, but conventions make things easier to understand across projects.

On the other hand, the following statement will pass a function to the onClick parameter of the button.

onClick={() => setCount(count + 1)}

It needs to be used as an arrow function to allow React handle the execution of the setter. Take a look at how this example is rendered in CodePen.


State as a snapshot

In React, to render changes to the UI, we need to update the state. Every change to the state will trigger a re-render, which is basically a snapshot of a component in time. The following things happen when React triggers a re-render:

- React calls your function component again.
- Your function returns a new JSX snapshot.
- React then updates the screen to match the snapshot your function returned.

To verify that React calls a function component again, you can add a console log and check what it prints in the browser console every time you click the increment button in the example above.

function Counter() {
  const [count, setCount] = useState(0)

  const timestamp =  Math.floor(Date.now() / 1000);
  console.log("timestmp: " +  timestamp)
...

Another interesting experiment we can run is trying to execute several calls to update the state like the following:

<button onClick={() => {
  setCount(count + 1)
  setCount(count + 1)
  setCount(count + 1)
}}>+3</button>

You might think that after clicking this button, the counter will increment by 3. However, as the current render is just a snapshot of the component in time, the code shown is equivalent to replacing the count by its value in a given moment. For instance, after the first render, the snapshot will look like:

<button onClick={() => {
  setCount(0 + 1)
  setCount(0 + 1)
  setCount(0 + 1)
}}>+3</button>

Clicking the button for the first time will update the state to 1 three times!.

Queueing state updates

React waits until all code inside an event handler has finished executing before processing state updates. This means that when you click the button above, React queues the three state updates and then commits them together in a single batch. As a result, React calls the component function only once, and the component renders using the updated state.

In some cases, we might need to queue more than one update to the state based on a previous state. The following modification will trigger the same three updates to the state, but it will increment the counter by three as expected.

<button onClick={() => {
  setCount(n => n + 1)
  setCount(n => n + 1)
  setCount(n => n + 1)
}}>+3</button>

let's see how this look in CodePen.



Acerca de Darío Rivera

Author

Application Architect at Elentra Corp . Quality developer and passionate learner with 10+ years of experience in web technologies. Creator of EasyHttp , an standard way to consume HTTP Clients.

LinkedIn Twitter Instagram

Sólo aquellos que han alcanzado el éxito saben que siempre estuvo a un paso del momento en que pensaron renunciar.