Using state
The component state is a special variable containing information about the component’s current situation. For example, a component may be in a loading state or an error state.
In this section, we’ll learn about state and use it within our alert component in the CodeSandbox project. We will use state to allow the alert to be closed by the user.
Understanding state
There isn’t a predefined list of states; we define what’s appropriate for a given component. Some components won’t even need any state; for example, the App
and Alert
components in our CodeSandbox project haven’t required state for the requirements so far.
However, state is a key part of making a component interactive. When a user interacts with a component, the component’s output may need to change. For example, clicking on a component may need to make an element in the component invisible. A change to a component state causes the component to refresh, more often referred to as re-rendering. So, a user could click on a component causing a state change, resulting in an element in the component becoming invisible.
State is defined using a useState
function from React. The useState
function is one of React’s hooks. React hooks were introduced to React in version 16.8 and give function components powerful capabilities such as state. There is a whole chapter on React hooks in Chapter 4, Using React Hooks.
The syntax for useState
is as follows:
const [state, setState] = useState(initialState);
Here are the key points:
- The initial state value is passed into
useState
. If no value is passed, it will initially beundefined
. useState
returns a tuple containing the current state value and a function to update the state value. The tuple is destructured in the preceding code snippet.- The state variable name is
state
in the preceding code snippet, but we can choose any meaningful name. - We can also choose the state setter function name, but it is common practice to use the same name as the state variable preceded by
set
. - Multiple states can be defined by defining multiple instances of
useState
. For example, here are definitions for loading and error states:const [loading, setLoading] = useState(true); const [error, setError] = useState();
Next, we will implement state in the alert component to determine whether it is visible or not.
Implementing a visible state in the alert component
We will begin by implementing a feature in the alert component that allows the user to close it. A key part of that feature is controlling the alert’s visibility, which we will do with a visible
state. This state will either be true
or false
and it will initially be set to true
.
Follow these steps to implement a visible
state in Alert
:
- Open
Alert.js
in the CodeSandbox project. - Add the following
import
statement at the top of the file to import theuseState
hook from React:import { useState } from 'react';
- Define the
visible
state as follows in the component definition:export function Alert(...) { const [visible, setVisible] = useState(true); return ( ... ); }
- After the state declaration, add a condition that returns
null
if thevisible
state isfalse
. This means nothing will be rendered:export function Alert(...) { const [visible, setVisible] = useState(true); if (!visible) { return null; } return ( ... ); }
The component will render in the Browser panel the same as before because the visible
state is true
. Try changing the initial state value to false
, and you will see it disappear in the Browser panel.
Currently, the alert component is making use of the visible
state’s value by not rendering anything if it is false
. However, the component isn’t updating the visible
state yet – that is, setVisible
is unused at the moment. We will update the visible
state after implementing a close
button, which we will do next.
Adding a close button to Alert
We will add a close button to the alert component to allow the user to close it. We will make this configurable so that the alert consumer can choose whether the close button is rendered.
Carry out the following steps:
- Start by opening
Alert.js
and add aclosable
prop:export function Alert({ type = "information", heading, children, closable }) { ... }
The consumer of the alert component will use the closable
prop to specify whether the close button appears.
- Add a close button between the heading and content as follows:
export function Alert(...) { ... return ( <div> <div> ... <span>{heading}</span> </div> <button aria-label="Close"> <span role="img" aria-label="Close">❌</span> </button> <div>{children}</div> </div> ); }
Notice that the span
element that contains the close icon is given an "img"
role and a "Close"
label to help screen readers. Likewise, the button is also given a "Close"
label to help screen readers.
The close
button appears in the alert component as follows:
Figure 1.5 – The close button in the alert component
- At the moment, the close button will always render rather than just when the
closable
prop istrue
. We can use a JavaScript logicalAND
short circuit expression (represented by the&&
characters) to render theclose
button conditionally. To do this, make the following highlighted changes:import { useState } from 'react'; export function Alert(...) { ... return ( <div> <div> ... <span>{heading}</span> </div> {closable && ( <button aria-label="Close"> <span role="img" aria-label="Close"> ❌ </span> </button> )} <div>{children}</div> </div> ); }
If closable
is a falsy value, the expression will short-circuit and consequently not render the button. However, if closable
is truthy, the button will be rendered.
Note
See the following link for more information about logical AND
short-circuit expressions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND.
See the following link for JavaScript’s falsy values, https://developer.mozilla.org/en-US/docs/Glossary/Falsy, and https://developer.mozilla.org/en-US/docs/Glossary/Truthy for truthy values.
- Open
App.js
and pass theclosable
prop intoAlert
:export default function App() { return ( <div className="App"> <Alert type="information" heading="Success" closable> Everything is really good! </Alert> </div> ); }
Notice that a value hasn’t been explicitly defined on the closable
attribute. We could have passed the value as follows:
closable={true}
However, there is no need to pass the value on a boolean attribute. If the boolean attribute is present on an element, its value is automatically true
.
When the closable
attribute is specified, the close
button appears in the alert component as it did before in Figure 1.5. But when the closable
attribute isn’t specified, the close button doesn’t appear:
Figure 1.6 – The close button not in the alert component when closable is not specified
Excellent!
A quick recap of what we have learned so far about React state:
- State is defined using React’s
useState
hook - The initial value of the state can be passed into the
useState
hook useState
returns a state variable that can be used to render elements conditionallyuseState
also returns a function that can be used to update the value of the state
You may have noticed that the close
button doesn’t actually close the alert. In the next section, we will rectify this as we learn about events in React.