React Component State (State)
In the previous chapter, we learned about props, which allows us to pass data from parent components to child components. However, props are read-only. Components cannot change their own props.
So, when a component needs to change its own data based on user interactions, network responses, or other events, what should we do? The answer is State (State).
State is similar to props, but it is private and completely controlled by the component itself.
Introducing useState Hook
In function components, we use the useState Hook to add state to components.
What is a Hook? Hooks are special functions introduced in React 16.8. They are special functions that allow you to use state and other React features in function components. We will dive deeper into Hooks in later chapters.
Let's look at an example. We will create a component with a clock feature that updates the time itself.
Previously we used setInterval and root.render() to implement it, but that's not component-oriented thinking. Now, let the Clock component manage its own state.
Code Analysis
-
const [date, setDate] = useState(new Date());- We call the
useStateHook and pass in the initial statenew Date(). useStatereturns an array containing two values:- The current state value (
date). - A function that can be used to update the state (
setDate).
- The current state value (
- We use array destructuring syntax
[date, setDate]to name these two values.
- We call the
-
useEffect(...)- The
useEffectHook is used to handle side effects, such as data fetching, subscriptions, or manually modifying the DOM. - Here, we use it to set up a
setIntervaltimer that runs every second. - The second parameter
[]is a dependency array. When the array is empty, it means this effect will only execute once after the component is first rendered to the screen (mounted). - The function returned by
useEffectis a cleanup function. It will execute when the component is removed from the screen (unmounted) to clear the timer and prevent memory leaks.
- The
-
setDate(new Date())- In the timer's callback function, we call
setDateand pass in a newDateobject. - This is the only correct way to update state.
- When
setDateis called, React will re-render theClockcomponent and use the latestdatevalue.
- In the timer's callback function, we call
State Updates are Asynchronous
When you call the setState function, React may batch multiple setState calls into a single update for performance optimization. This means this.props and this.state may be updated asynchronously, and you should not rely on their values to calculate the next state.
For example, the following code may not work as expected:
Because the count value doesn't change during the same render, the three calls to setCount have the same effect as one call.
The Correct Approach: Use Functional Updates
If you need to calculate the new state based on the previous state, you can pass a function to setState. This function will receive the previous state as a parameter and return the new state.
Now, each call to setCount receives the latest state after the previous update, and count will eventually increase by 3.
Summary
stateis used to store data that changes over time within a component.- Use
useStateHook to add and manage state in function components. - Calling
useStatereturns the current state and a function to update state[value, setValue]. - Call the
setValuefunction to update state, which triggers a component re-render. - State updates may be asynchronous; use functional updates when the new state depends on the old state.
Next, we will learn another important concept of components: lifecycle.