State and Hooks

Creating a stateful component that will rerender new data when the app updates.

Learning Goals

At the end of this Tutorial, you will be able to:

  • Create a simple counter app to demonstrate how state works in ReactJS.

About state in ReactJS

As you learned in the Working with Props Tutorial, data passed into a functional component as an argument cannot be changed by that component.

Often, however, the reason you create a function is in order for it to change data!

In ReactJS, data inside a function that is changed in some way by the function is called state. Furthermore, ReactJS provides special functions called hooks for managing state (data that can change) inside components.

So if you want to change data in your app, you need to store that in state so that it properly re-rendered once the data actually changes.

The most commonly-used hook is called useState. It enables you to manage state (data that may change) inside a functional component. And when the data changes, the component will re-render the new data to the DOM.

Components that do not change the value of their props have no state - they are said to be stateless components.

In this Tutorial, you will create a simple counter app to demonstrate how state works in ReactJS.

Creating your counter app with CRA

Follow the steps below.

  1. In a Command Prompt window or inside a VS Code Terminal, navigate to where you want Vite to create a folder for your app. For example:
    C:\> users\react\apps
  2. Type the following command that includes the name you want to call your new app. In this example, the app is called reactjs-hooks.
  3. Type the following command that includes the name you want to call your new app.
    npm create vite@latest reactjs-hooks -- --template react
  4. When Vite completes the build process, you will see the message below. screenshot
  5. Follow these instructions to continue building your app, and then running it.

When you launch your new app in a browser, it should look as shown below.

screenshot

Customising your app

Next, you will customise the 'boilerplate' content provided by Vite.

  1. Download the following stylesheet and save it to your app's /src folder.   Counter.css
  2. Open the index.html file in your main app folder and replace the <title> tag as shown below. screenshot
  3. In your /src folder, open the main.jsx file and update it as follows. screenshot
  4. Also in your /src folder, open the App.jsx and replace all its content with the content below.
  5. import './Counter.css'
    function App() {
      return (
    	<>
    	  <h1>Hello, World!</h1>
    	  <p>Paragraph of text.</p>
    	</>
       );
    }	
    	
    export default App;

Your web page should now look as shown below.

Sample React screen

Adding a stateful component

Next, you will add a counter component to your basic app.

  1. In the /src folder, create an IncrementDecrement.jsx file with the following content.
    
    import { useState } from 'react';
    	
    function IncrementDecrement() {
       const [count, setCount] = useState(0);
          return (
             <div>
                <button onClick={() => setCount(count + 1)}>+</button>
                {count}
                <button onClick={() => setCount(count - 1)}>-</button>
             </div>
        )
    }
    	
    export default IncrementDecrement;
  2. Also in the /src folder, update the App.jsx file with the following content.
    
    import IncrementDecrement from './IncrementDecrement';
    import './Counter.css'
    
    function App() {
      return (
        <div className="box-counter">
          <IncrementDecrement />
        </div>
      )
    }
    		
    export default App;

Your web page should now look as shown below.

screenshot

How state is updated with a hook

The following explains how state is updated inside the IncrementDecrement.js component.

  • At the top of the component, the useState hook is imported as shown below:
       import React, { useState } from 'react';
  • Next is a functional component that contains the code that will perform the updating.
       function IncrementDecrement() {
        // Code for updating state goes here
    }
    
  • You will want this function to be available to the main or top-level App.js component. So you wiil add an export default instruction at the end of the file.
      export default IncrementDecrement;
  • The main work is performed inside the function with this line:
       const [count, setCount] = useState(0);
    This line does two things:
    • It declares a new state variable named count.
    • It declares a function named setCount that, when called by the user's click action. will update the current value in the count state variable.
    The useState hook takes a single argument, which is the initial value of the state variable. In this case, the initial value is 0. screenshot
  • Attached to each of the two buttons is an event handler that captures the user's click action.   In ReactJS, event names are written in camelCase (in this case as onClick) and not in JavaScript lowercase style (onclick).
       <button onClick= ... ></button>
  • Another difference is that with JSX you pass a function as the event handler within curly braces {}, rather than a string between quotes "".
       // In JavaScript
    <button onclick="activateLasers()">Activate Lasers</button>
    // In JSX
    <button onClick={activateLasers}Activate Lasers</button>
  • In each case, the event handler is an arrow function that calls the setCount function to update the value in the count state variable.
       <button onClick={ () => // called function goes here }>+</button>
  • Below is the syntax of the called arrow function.
       => setCount(Count + 1)
  • And finally, this displays the current value of the count state. It will be updated and re-rendered every time count is reset the setCount() updater function.
       {count}