useState - what, when and why?
32
1

useState - what, when and why?

useState is a good way for us to declare our state variables inside our components. Do you know how to use it and what it is?

Daniel Silva
3 min
32
1
Email image

useState is a way for us to declare our state variables inside our components.

When React was on class paradigm, we would define our states inside our constructors.

For example:

class ClassComponent extends React.Component {
constructor(props) {
super(props);
this.state = {initialState}
}
...
}

When we started using the functional components, we didn't have the constructors anymore, so the hooks were created... Now we can handle our state variables like that:

const FunctionalComponent = () => {
const [stateValue, setStateValue] = useState(initialState)
...
}

It is simpler, has less lines, but that are a lot of concepts behind this code.

When we call useState() some properties are returned inside an array. What we are doing above is destructuring our array.

In the first element of our array we have the value of our state, in this case we named it as stateValue.

The second element of our array is our updating function. This function will be responsible for changing our stateValue, in the case above, our function is called setStateValue.

Jumping over the destructuring, inside our useState(), we have our initialState. This initial state can be of different types, as string, number, boolean, array, object, or an array of objects, you are the one who decides it.

To update the value, call the function passing the new value:

...
const updateStateValue = () => {
setStateValue(newValue)
}
...

But wait a minute... It's not that simple.

This method above is only used when you want to update your state that has simple types of data, like string, number or array. Because when you call setStateValue() what it does is to substitute the previous state with the new one.

const FunctionalComponent = () => {
const [planets, setPlanets] = useState('mercury')
const updatePlanetsState = (planet) => {
setPlanets(planet)
}
console.log(planets)
updatePlanetsState('venus')
console.log(planets)
}

So if you have an array of string and you set the new state as a string, the array will be gone and now you will have just an string as the example below:

const FunctionalComponent = () => {
const [planets, setPlanets] = useState(['mercury', 'venus', 'earth'])
const updatePlanetsState = (planet) => {
setPlanets(planet)
}
console.log(planets)
updatePlanetsState('mars')
console.log(planets)
}

As you can see, this is not recommended to do on React, the best approach is that your states stays with the same type - typescript is good for that because if you do something as the code above, it will alert you -.

We transformed an array state into a string state. It can cause some bugs and can be hard to understand this code when it's shared with a big team or if you have to maintance it after a while.

Ok, but I could replace the array with another array added by the planet I want, right? This is what it would look like:

const FunctionalComponent = () => {
const [planets, setPlanets] = useState(['mercury', 'venus', 'earth'])
const updatePlanetsState = (planets) => {
setPlanets(planets)
}
console.log(planets)
updatePlanetsState(['mercury', 'venus', 'earth', 'mars'])
console.log(planets)
}

You could do this, but as you can see this code does not smells good. It's not reusable, and you will have to write the array every time that you want to add a new planet repeting lines and lines of code.

The cleaner way to code this is accessing the previous value when you call setState(). So you can spread, add and change it. Adding a planet to this state, would be something like:

const FunctionalComponent = () => {
const [planets, setPlanets] = useState(['mercury', 'venus', 'earth'])
const updatePlanetsState = (planet) => {
setPlanets((prevState) => ([...prevState, planet]))
}
console.log(planets)
updatePlanetsState('mars')
console.log(planets)
updatePlanetsState('jupiter')
console.log(planets)
}

This prevState that we access inside the state function setPlanets(), is the state value before we change it. You can name this variable as you please.

Hmm, OK. I'm understanding what you are saying. What about updating an object state?

It's very similar to the example above. I'm gonna show you a full code of a component where we can change values of an object.

const Planet = () => {
const [planet, setPlanet] = useState({
id: 42,
name: 'Earth',
surfaceTemp: 14,
})
const increaseTemperature = () => {
setPlanet((prevState) => ({
...prevState,
surfaceTemp: prevState.surfaceTemp + 1,
}))
}
const decreaseTemperature = () => {
setPlanet((prevState) => ({
...prevState,
surfaceTemp: prevState.surfaceTemp - 1,
}))
}
return (
<div>
<h1>
The temperature on {planet.name} is {planet.surfaceTemp}°C
</h1>
<button type="button" onClick={increaseTemperature}>
Increase Temperature
</button>
<button type="button" onClick={decreaseTemperature}>
Decrease Temperature
</button>
</div>
)
};
export default Planet;

You can access this code on CodeSandBox.

Hope you all liked it. Stay tuned to receive more content about the React world.


Share this Content
Follow my Channel

Bibliography

1. https://reactjs.org/