React useState: The Complete guide
React useState: the complete guide

React useState: The Complete guide

Dead Simple Chat Team

Table of Contents

In this article we are going to learn about react useState.  useState is a React Hook that lets you add a state variable to your component.

const [state, setState] = useState(initialState);

If you are looking for a React Native Chat SDK to build in app chat messaging application, you can consider DeadSimpleChat React Native SDK

Reference

Call useState at the top level of your component to declare a state variable

import { useState } from 'react';

function MyComponent() {
  const [age, setAge] = useState(28);
  const [name, setName] = useState('Taylor');
  const [todos, setTodos] = useState(() => createTodos());
  // ...

The convention is to name state variables like [something. setSomething] using array de structuring

Parameteres

  • initialState: the value that the state would have initially. This could be any value but there is special behaviour for functions. This value is ignored after the initial render

As for the functions, if you assign the state a function. It should be a pure function, meaning it should not take any parameters and should return value of any type.

React will call the initializer function and store its return value in the initial state, when initializing the component

Returns

useState returns two value, these are

  1. the current state and
  2. the set function with the ability to update the state with a different value and trigger a re render

Note: if you want to store values but do not want to trigger a component re render use useRef instead of useState

Note: When the component renders for the first time the value of the useState will be equal to the initialState that you have passed

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Pitfalls

  • You can only call useState at the top of your component or your own Hooks. You cannot call useState inside of a loop or conditions.
  • If you want to useState inside conditions or loops extract a new component and move the state to that component

Here is an example

import React, { useState } from 'react';

function TodoListCreator({ todos }) {
  return (
    <ul>
      {todos.map((todo, index) => {
        // ❌ Wrong useage: useState is called inside a loop
        const [isComplete, setIsComplete] = useState(false);

        return (
          <li key={index}>
            <input
              type="checkbox"
              checked={isComplete}
              onChange={() => setIsComplete(!isComplete)}
            />
            {todo}
          </li>
        );
      })}
    </ul>
  );
}
Wrong way to useState

Fixing the issue and extract the useState to a new component

import React, { useState } from 'react';

function TodoItem({ todo }) {
  // ✅ Right useageL extracting the useState at the top of a component
  const [isComplete, setIsComplete] = useState(false);

  return (
    <li>
      <input
        type="checkbox"
        checked={isComplete}
        onChange={() => setIsComplete(!isComplete)}
      />
      {todo}
    </li>
  );
}

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo, index) => (
        <TodoItem key={index} todo={todo} />
      ))}
    </ul>
  );
}
right useage
  • In strict mode the react will call your render function twice. This should not cause any problems if your render function is pure as it should be. Pure meaning it should return the same output for same input

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Usage

Adding state to a component. useState lets you add state to your functional components

Let us understand this with an example

import { useState } from 'react';

function MyComponent() {
  const [age, setAge] = useState(42);
  const [name, setName] = useState('Brian');
  // ...

The useState will return an array with 2 items

  • the current state of this state variable. It is initially set to the initial state that you provided
  • the set  function using which you can set the state to any other value

To update what is on the screen, let us update the state using the useState function

function handleClick()
	setName('Billo');
    };

React will update the state and re render the component update with the new data.

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

gotcha

Calling the set function will not change the current state in already executing code. It will only affect what the useState will return when the component re renders

function handleClick() {
  setName('Billo');
  console.log(name); // Still "Brian"!
}

Let us consider some of the examples

import { useState } from 'react';

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You clicked the button {count} times
    </button>
  );
}

Here we are showing how to useState in a simple counter component

  1. We are importing the state from react
  2. we create the Counter component and set the initial state using the setState function to 0
  3. Then we create the handleClick function (that is a event handler function, its called when the click event happens)
  4. Then on the handle click function we use the setCount to increase the count by 1 everytime the button is clicked
  5. Lastly we return the JSX and render the component the text in the button shows how many times the button has been clicked

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Example 2 Simple Input Component

In this example we will use a simple input component using React and our useState hook. Let us

import { useState } from 'react';

export default function MyInput() {
  const [text, setText] = useState('My name is ');

  function handleChange(e) {
    setText(e.target.value);
  }

  return (
    <>
      <input value={text} onChange={handleChange} />
      <p>You typed: {text}</p>
      <button onClick={() => setText('My name is ')}>
        Reset
      </button>
    </>
  );
}

In brief we have a state variable called text it has a string (My Name is ). When the user types the handleChange event handler function reads the input text from the DOM element and calls the setState method to update the state.

It allows the code to show the text below in the p tag.

When the user clicks on the Reset button the onClick method calls the setState method setText to change the text to hello again  

example

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Updating state using the previous state

lets consider the example below

function handleClick() {
  setAge(age + 1); // setAge(22 + 1)
  setAge(age + 1); // setAge(22 + 1)
  setAge(age + 1); // setAge(22 + 1)
}

Suppose the age of the user is 22. The handler handleClick calls the setAge(age + 1) three times

but after one click the age is 23 and not 25. This is because the set function doesn't update the state when the code is running. It updates the state on the next re render

So the setAge(age + 1 ) becomes 23 and not 25

We can solve this problem by passing an updater function to the set function that is setAge like

  function handleClick() {
    setAge(age => age + 1); // setAge(22 => 23)
    setAge(age => age + 1); // setAge(23 => 24)
    setAge(age => age + 1); // setAge(24 => 25)
  }

Herer age => age + 1 is your updater function. This function takes the pending state and gives the updated state

React puts the updater functions in a queue, then during next render calls them in the same order.

Now the function above updates like this

  • setAge(age => age + 1); // setAge(22 => 23) In this case the age variable has value 22 and then becomes 23  
  • setAge(age => age + 1); // setAge(23 => 24)  In this case the age variable has value 23 and then becomes 24
  • setAge(age => age + 1); // setAge(24 => 25)   In this case the age variable has value 24 and then becomes 25

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Updating Objects and Arrays in state

You can put Objects and arrays in state as well. But remember state is readonly so remember to put in a new Object or an array instead of mutating existing objects

for example if you have a form in state don't mutate it

like so

// 🚩 Don't mutate an object in state like this:
form.firstName = 'Brian';

Instead create a new object and replace the existing one in the state

// ✅ Replace state with a new object
setForm({
  ...form,
  firstName: 'Brian'
});

Let us consider an example to better understand

A form state variable holds an Object.

We have input fields.

Each input field has an event handler function that calls the setForm with the entire state of the form

the {...form} syntax ensures that the entire form is replaced rather than mutated

import { useState } from "react";

export default function Form() {
  const [form, setForm] = useState({
    firstName: "billo ",
    lastName: "awesome",
    email: "billoawesome@person.com"
  });

  return (
    <>
      <label>
        First name:
        <input
          value={form.firstName}
          onChange={(e) => {
            setForm({
              ...form,
              firstName: e.target.value
            });
          }}
        />
      </label>
      <label>
        Last name:
        <input
          value={form.lastName}
          onChange={(e) => {
            setForm({
              ...form,
              lastName: e.target.value
            });
          }}
        />
      </label>
      <label>
        Email:
        <input
          value={form.email}
          onChange={(e) => {
            setForm({
              ...form,
              email: e.target.value
            });
          }}
        />
      </label>
      <p>
        {form.firstName} {form.lastName} ({form.email})
      </p>
    </>
  );
}
updating object in state examples

Let us understand this in detail

we have a Form component. then we initialize the state using initial values of

firstname

lastname

and email

lastly we render the component

The onChange event handler for each input calls the setForm method providing a new Object for the state. The spread syntax {...form} is used to copy all existing fields from the old object to the new object.

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Avoiding recreating the initial state

React saves the initial state once and ignores it on the next re renders

function TodoList() {
  const [todos, setTodos] = useState(createInitialTodos());
  // ...

although the result of the function createInitialTodo is used once. the react is calling it on every re render this can cause expensive re render and a waste of resources. If the function does some computationally intensive task or has a large object or array.

to solve this pass an initializer function to useState

function TodoList() {
  const [todos, setTodos] = useState(createInitialTodos);
  // ...

Notice that you are calling useState with createInitialTodos instead of  createInitialTodos() which is a function in itself and not  createInitialTodos()  which is the result of calling the function

React may call initializers twice in development to ensure that they are pure

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Resetting State with a Key

You will often see the key attribute when rendering lists. However there is one more purpose that it serves and that is to

reset a components state by passing a different key to a component

Let us consider an example to understand this

import { useState } from "react";

export default function App() {
  const [version, setVersion] = useState(0);

  function handleReset() {
    setVersion(version + 1);
  }

  return (
    <>
      <button onClick={handleReset}>Reset</button>
      <Form key={version} />
    </>
  );
}

function Form() {
  const [name, setName] = useState("Brian");

  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <p>Hello, {name}.</p>
    </>
  );
}

In this example the reset button changes the version state variable,  by setVersion(version + 1)

We are passing the version state variable as key to the Form component

when the key changes that is the version variable changes the react re renders the form and so the state gets reset

In other words,

The App component renders a Form component.

When reset button is clicked the handleClick event handler function is called which in turn changes the version to version plus 1

version acts as a key to the Form component. When the key changes the react re renders the form component along with all its children and thus the state gets reset.

Conclusion

In this article we learnt about the useState and how it can help us in creating react applications

I hope you like the article, we used extensive and easy to understand examples to explain the concepts.

I hope you liked the article

Thanks for reading