Course: Section

Get Started with Modern React: Step by Step

Episode: Title

S02・V08: State (Part 1)

Date Created: July 17th, 2019
Last Updated: 27 days ago

Objectives
  1. We will explain what component state is.
  2. We will use the React Hook “useState” to deal with component state.
  3. We will use the React Hook “useEffect” to deal with side-effects.
  4. We will state the rules for using React Hooks.
Watch Video
Duration: 7m 41s

State

We have already looked at React’s mechanism for passing data from a parent component to a child component, using props. React also has a way of remembering and updating data within a component, using a mechanism called “state”. In this video, we will explain what “state” is in more detail, and how to use it within a React function component.

Let’s create a component that we will call Example. We want the Example component to remember a piece of information. The information we want remembered is a numerical count of how often a button was clicked. We will have the Example component show the “count”, and also render the button to be clicked.

const Example = () => {
  // Remember the state of “count”

  return (
    <div>
      <p>You clicked {count} times</p>
      <button>
        Click me
      </button>
    </div>
  );
};

Now, we will need to import React and ReactDOM at the top of the file. And we can render the Example component to the DOM.

import React from "react";import ReactDOM from "react-dom";
const Example = () => {
  // Remember the state of “count”

  return (
    <div>
      <p>You clicked {count} times</p>
      <button>
        Click me
      </button>
    </div>
  );
};

ReactDOM.render(<Example />, document.getElementById("root"));

The variable “count” is not yet defined.

In function components such as Example, we can use a React “hook” to define the variable “count”, so that the component can remember it, and also update it. “Hooks” were introduced in React version 16.8.

In our example, the “count” variable will be a state variable. The React Hook that we need is called useState, which is a method we have available in the imported React library. The useState method takes the initial value of the variable it is keeping track of.

Let’s call this value initialCount. Since the “count” represents the number of times the button has been clicked, we should start the variable at zero.

useState Hook

Now, the useState method outputs an array with two elements. The first element in the array is the state variable that we want to have the component remember. Using array destructuring assignment, we can call the first element count.

The second element in the array is a function with which we can update the state variable. Conventionally, for the state updater function, we add the prefix “set” to the state variable. Again, using array destructuring assignment, we can name the second element setCount.

import React from "react";
import ReactDOM from "react-dom";

const Example = () => {
  const initialCount = 0;  const [count, setCount] = React.useState(initialCount);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button>
        Click me
      </button>
    </div>
  );
};

ReactDOM.render(<Example />, document.getElementById("root"));

We can now see that our Example component is rendering to the page.

The button will not respond to the user clicking on it yet. We will give the button an onClick event handler. We will pass an anonymous function, which will update our count state using the setCount updater function. The setCount function takes the value we want to set the count to, which is its current value plus one.

import React from "react";
import ReactDOM from "react-dom";

const Example = () => {
  const initialCount = 0;
  const [count, setCount] = React.useState(initialCount);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>        Click me
      </button>
    </div>
  );
};

ReactDOM.render(<Example />, document.getElementById("root"));

We can now test it out in the browser, by clicking the button 3 times. Our Example component works as intended.

Generally, we import the useState hook from its named React export. Then we delete the reference to React when we call useState.

import React, { useState } from "react";import ReactDOM from "react-dom";

const Example = () => {
  const initialCount = 0;
  const [count, setCount] = useState(initialCount);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
};

ReactDOM.render(<Example />, document.getElementById("root"));

Let’s think about the Example function component and what is going on here. Normally, variables “disappear” when a function exits. However, because of the useState hook, React preserves the state of count between re-renders of the function component.

useEffect Hook

Another very important React hook enables us to perform “side-effects”, such as data fetching, subscriptions, or manually changing the DOM. These effects cannot be done during rendering.

The “effect hook”, which is called useEffect, adds the ability to perform side effects from a function component. We can import it from its named React export.

For example, let’s say we want to set the document title after React updates the DOM. We will call the useEffect function to perform this side-effect. The useEffect hook has a required input argument, the so-called “effect” function. We will now define the effect function. We will use it to update the document title using the browser API.

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const Example = () => {
  const initialCount = 0;
  const [count, setCount] = useState(initialCount);

  const effect = () => {    document.title = `You clicked ${count} times`;  };  useEffect(effect);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
};

ReactDOM.render(<Example />, document.getElementById("root"));

We can now test it out in the browser. We will click on the button twice. You can see that the title has updated.

When you call useEffect, you’re telling React to run your “effect” function after updating the DOM. Effects are declared inside the component so they have access to its props and state. By default, React runs the effects after every render — including the first render.

Hooks are JavaScript functions, but they impose two additional rules.

  1. Only call Hooks at the top level of your component. Don’t call hooks inside loops, conditions, or nested functions.
  2. Only call Hooks from React function components, not from regular JavaScript functions.

Summary

We explained what component state is. We used the React Hook “useState” to deal with component state. We used the React Hook “useEffect” to deal with side-effects. And, we stated the rules for using React Hooks.

Next Up…

In the next video, we will continue discussing component state.