To keep track of how our data changes in React, we use state management. By doing so, we can create dynamic apps that respond to user input.
There are several ways to manage state in React, including Redux and Class-based state management. In this article, we’ll see how to use React useState to manage state on functional components.
React useState hook lets us add state to function components.
useState
takes an initial state as an argument and returns an array with 2 values:
To import useState:
import { useState } from 'react';
In this example, we pass an empty string as our default state
const [state, setState] = React.useState('');
In this basic example, we implement a useState hook to create a simple Count App.
import React, { useState } from 'react'
export default function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Counter App</h1>
<button onClick={() => setCount(count + 1)}>Count {count}</button>
</div>
)
}
In this example, we’ll set state based on previous state value.
Once again, we’ll create a Counter App. However, this time it will have buttons to increment, decrement and reset the count value.
To update the value based on the previous value, we pass in a function that takes the previous state value
onClick={() => setCount(prevCount => prevCount - 1)}
Don’t do this
setCount(count - 1)
Put it all together
import React, { useState } from 'react'
export default function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Counter App</h1>
<h2>{count}</h2>
<button onClick={() => setCount(prevCount => prevCount - 1)}>
Decrease
</button>
<button onClick={() => setCount(0)}>
Reset
</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>
Increase
</button>
</div>
)
}
In this example, the default state value wil be an array.
We will create 2 buttons to
import React, { useState } from 'react'
const UseStateArray = () => {
const data = [
{ id: 1, name: 'Anna' },
{ id: 2, name: 'Joe' },
{ id: 3, name: 'Pan' },
{ id: 4, name: 'Ron' },
];
const [people, setPeople] = useState(data);
// Set removeItem function
const removeItem = (id) => {
let newPeople = people.filter((person) => person.id !== id);
setPeople(newPeople);
};
return (
<div>
{people.map((person) => {
const { id, name } = person;
return (
<div key={id} className='item'>
<h4>{name}</h4>
<button onClick={() => removeItem(id)}>Remove</button>
</div>
);
})}
// Button to remove the whole list
<button className='btn' onClick={() => setPeople([])}>
Clear list
</button>
</div>
)
}
export default UseStateArray;
In this example, the default state value wil be an object. We will create a button to change the message.
If we use an object inside our state, when updating the object, we need to make sure we update all values in the old object as well because they don’t get merge automatically.
import React, { useState } from 'react';
const UseStateObject = () => {
const [person, setPerson] = useState({
name: 'Anna',
age: 20,
message: 'Random Message',
});
const changeMessage = () => {
setPerson({ ...person, message: 'Hello World' });
};
return (
<div>
<h3>{person.name}</h3>
<h3>{person.age}</h3>
<h4>{person.message}</h4>
<button className='btn' onClick={changeMessage}>
Change message
</button>
</div>
);
};
export default UseStateObject;
To preserve all values in the object, we use spread operator: …person