CodeNewbie Community 🌱

Cover image for Applying the useState Hook to an old React project
McKenna Bramble
McKenna Bramble

Posted on

Applying the useState Hook to an old React project

✨ Hello! ✨

In this post, I will be updating the code from an old React project. I will be converting the class (aka "stateful") component into a function (aka "stateless") component that utilizes the useState Hook. This is by no means a comprehensive guide to the useState Hook, but my hope is that this can be a light introduction to useState and Hooks, and perhaps a helpful reference. Thank you for reading!

πŸ€” What the heck is a Hook?

If you are completely new to React Hooks, React Docs has an in-depth explanation. To summarize, Hooks are JavaScript functions that allow us to utilize the React state and lifecycle features without using class components. Hooks cannot be used in class components. Instead, they are used in function components. In this article, I will be going over the useState Hook, but there are others built-in to React (e.g. useEffect) and you can also make your own Hooks, but I'm not at that level of understanding quite yet πŸ˜‰.

✏️ useState syntax

I found it helpful to understand the syntax of calling useState before getting too far, so here is a brief explanation.

To call useState, you will write something similar to the code below inside of a function component:

const [state, setState] = useState(initialState);
Enter fullscreen mode Exit fullscreen mode

Calling useState will return two values, shown inside of the brackets in the above code. The first value (state in the brackets above) is the current state aka "state variable." The second value (setState in the brackets above) is a function that updates the current state. useState only accepts one argument, which is the initial state (initialState in the code above).

This might be confusing if you are new to Hooks, but hopefully seeing it in use in my project will provide some context.

πŸ‘€ My project code (before Hooks)

Let's take a look at my Chalkboard project that uses a class component to set the state instead of Hooks. Feel free to toggle the preview panel to see how the code is rendering.

*Those of you who are seasoned in React might notice my lack of keys for the list items. In this project, that was not my focus, so I am just leaving them out for now.

πŸͺ„ Let's switch it up

Below is all of the code I changed in order to utilize the useState Hook.

Note that the original code that uses a class component is in white, while the updated code that uses the function component with the useState Hook is in color.

1. Importing

In a class component, we import Component from React:

import React, { Component } from "react";
Enter fullscreen mode Exit fullscreen mode

With the State Hook, we instead import useState from React:

import React, { useState } from "react";
Enter fullscreen mode Exit fullscreen mode

2. Initializing state

Class components allow us to use the setState method, which is built-in to the base Component class. Without Hooks, you need to "extend" the React Component's features to your class component. In this case, my component is called Chalkboard. You will also notice that in order to initialize state in the class component, it needs to be written as an object:

class Chalkboard extends Component {
  state = {
    chalk: "",
    notes: []
  };
Enter fullscreen mode Exit fullscreen mode

When using Hooks, you do not need to use a class component, and can instead write your component as a function component (still capitalizing the first letter of the component's name so React recognizes it!). In order to initialize state in a function component, you will call the useState Hook. This is where the syntax I talked about before comes in! In my code below, my current state aka "state variable" for the chalk is chalk; the function that I will use to update the state is called setChalk; and the initial state that is passed to useState is an empty string "". The same logic is followed with the notes state:

function Chalkboard() {
  const [chalk, setChalk] = useState("");
  const [notes, setNotes] = useState([]);
Enter fullscreen mode Exit fullscreen mode

3. Updating state

In class components, we use this.setState to update the state:

updateChalk = (event) => {
    this.setState({ chalk: event.target.value });
  };
Enter fullscreen mode Exit fullscreen mode

In function components, we will use the function defined when we initially called the useState Hook. Additionally, functions within the component need to be defined with const:

const updateChalk = (event) => {
    setChalk(event.target.value);
  };
Enter fullscreen mode Exit fullscreen mode

Below is another event handler. This has a few more lines of code than the updateChalk handler that need to be updated. In class components, we need to use this.state to make changes to the state:

updateNotes = (event) => {
    event.preventDefault();
    var newNotes = this.state.notes.slice();
    newNotes.push(this.state.chalk);
    this.setState({
      chalk: "",
      notes: newNotes
    });
  };
Enter fullscreen mode Exit fullscreen mode

I removed this.state from the lines of code referencing it, and used the setChalk and setNotes functions instead of this.setState:

const updateNotes = (event) => {
    event.preventDefault();
    var newNotes = notes.slice();
    newNotes.push(chalk);
    setChalk("");
    setNotes(newNotes);
  };
Enter fullscreen mode Exit fullscreen mode

4. Rendering the UI

Class components require a render() method to return JSX. Inside of the render() method, the notes variable maps over the notes array and is later rendered in the return statement:

render() {
    var notes = this.state.notes.map((note) => <li>{note}</li>);

    return (
      <div className="App">
        <form onSubmit={this.updateNotes}>
          <input
            type="text"
            placeholder="type here"
            value={this.state.chalk}
            onChange={this.updateChalk}
          />

          <input type="submit" />
        </form>

        <div className="board">
          <h1 className="chalk">{this.state.chalk}</h1>
        </div>

        <ul className="notes">{notes}</ul>
      </div>
    );
  }
Enter fullscreen mode Exit fullscreen mode

Function components do not have the render() method, so the notes variable needs to be changed a bit. Because it is no longer in a render() method, the variable name needs to be changed to something that hasn't already been declared. In this case, I have updated it to notesList. I also removed all instances of this.state in the return statement:

const notesList = notes.map((note) => <li>{note}</li>);

  return (
    <div className="App">
      <form onSubmit={updateNotes}>
        <input
          type="text"
          placeholder="type here"
          value={chalk}
          onChange={updateChalk}
        />

        <input type="submit" />
      </form>

      <div className="board">
        <h1 className="chalk">{chalk}</h1>
      </div>

      <ul className="notes">{notesList}</ul>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

πŸ₯³ That's it!

Here is the CodeSandbox of my updated project (with Hooks!).

⚑ Final thoughts

Converting my old project from a class component to a function component with Hooks definitely helped me understand how to use useState in the future! I like that it requires less code, and not needing to use this.state is great. The biggest adjustment I had to make was understanding how to use the setChalk and setNotes functions to update the state rather than this.setState.

I hope this was a helpful introduction to the State Hook. Thank you for reading!

πŸ“Έ cover image created by me!

Top comments (6)

Collapse
 
sheblair profile image
sheila

mckenna, this is awesome! you did such a great job explaining hooks and functional components. this is so relevant to me because just today i started converting my sticky notes app from class components to functional components w/ hooks! sooo i'm with ya all the way 🀠

Collapse
 
mckennabramble profile image
McKenna Bramble

Thank you Sheila!! I'm glad it was helpful 😁 Good luck with the sticky notes project!

Collapse
 
twosavoie profile image
Lisa Savoie

Fantastic article McKenna! You did an amazing job explaining the updates!

Collapse
 
mckennabramble profile image
McKenna Bramble

Thank you!!!!

Collapse
 
taurist profile image
Tauri StClaire

This is AMAZING and VERY THOROUGH McKenna, well done! I will definitely be using this as a reference when I'm ready to tackle hooks myself!

Collapse
 
mckennabramble profile image
McKenna Bramble

Thank you! I am hoping to start posting a technical blog once a week moving forward 🀞🀞🀞