Hooks are available in React since v16.8. It’s a new and different way of using state and other React features without the need of class. Also, you may share this state/logic by writing custom and reusable hooks.
We will call
useStateinside a function component to add some local state to it.
React will know about this state and it will preserve this state between re-renders.
import React, { useState } from 'react'
const MyFunctionalComponent = () => {
const myState = useState('')
}When calling useState it’s better to use array destructuring.
useState only takes one argument, the initial state. useState returns an array,
import React, { useState } from 'react'
const MyFunctionalComponent = () => {
const [name, updateName] = useState('')
}You can also use other arguments to initialize your state, like booleans, even an object or array.
const MyFunctionalComponent = () => {
const [isPlaying, updatePlaying] = useState(false)
const [userSettings, updateUserSettings] = useState({
userName: 'fermaddev',
race: 'human',
items: ['potion', 'blade', 'shield'],
})
}If updatePlaying or updateUserSettings gets called, React will know about the new state an will re-render the component.
There are two main rules you should pay attention when using hooks:
Read more about React Hook Rules
import React, { Component } from 'react'
export default class extends Component {
constructor() {
super()
this.state = {
count: 0,
}
}
handleClick = () =>
this.setState(prevState => ({
count: prevState.count + 1,
}))
render() {
return (
<div>
Class Count: {this.state.count}
<button onClick={this.handleClick}>Increment!</button>
</div>
)
}
}import React, { useState } from 'react'
export default function() {
//create initial state for count
const [count, setCount] = useState(0)
//you can pass an updater function to setCount (like in setState)
//the updater function will have access to the previous state
const handleClick = () => setCount(prevCount => prevCount + 1)
return (
<div>
Count: {count}
<button onClick={handleClick}>Increment!</button>
</div>
)
}The beauty of useState it can also accept an object or array as it’s argument.
The only gotcha is that everytime that you call the updater function (in this example setState), the whole state wil be wiped out.
So we have to explicitly set the previous state and merge it with the new piece of state that has changed.
Let’s re-build the React Class setState functionality using hooks!
import React, { useState } from 'react'
export default function() {
const [state, setState] = useState({})
function handleChange(e) {
e.persist()
const { name, value } = e.target
mergeState({ name: value })
}
function mergeState(newState) {
setState(prevState => ({
...prevState,
...newState,
}))
}
const { name, twitter, age } = state
return (
<div>
<h3>Name: {name}</h3>
<input type="text" name="name" onChange={e => handleChange(e)} />
<h3>Twitter: {twitter}</h3>
<input type="text" name="twitter" onChange={e => handleChange(e)} />
<h3>Age: {age}</h3>
<input type="number" name="age" onChange={e => handleChange(e)} />
</div>
)
}Then, should I use an object to store all my state or have small pieces of space using useState multiple times?
Answer: It’s up to you, whatever makes more sense for the component that you are building!
You can read more about React Hooks here.
Hope you enjoyed reading, Happy hacking! 👻