Photo by Christopher Gower on Unsplash
React state management - Part 1: Introduction & local state management
Find out how state management works in React, starting with local state management
Introduction
While building a website using React, one of the most important things that you'll heavily use and rely upon is managing your state.
Throughout this series, I'll illustrate on the best use cases and ways to manage state throughout my applications and websites.
What is React?
More than a decade ago, developers used to build websites using Vanilla JS, while writing a lot of redundant code, resulting in longer processes. After a couple of years, developers were able to use newly introduced JS Frameworks based on UI components. This made the process easier and shorter to produce modern websites, with extra features such as re-using any component on our website. React thus was born (by Facebook), and today it's simply the most popular JS framework around.
What is React state management?
Each React component have a built-in state object, where you store data/assets that are persistent between component renderings. We can manage any component state locally or using an external state management library.
Local state management
Throughout this part of the series, We'll talk about managing our state locally.
Whilst React ships with many useful hooks, one of the most widely used ones is the useState()
hook.
Well first, what is a hook exactly?
From the official docs, a Hook is a special function that lets you โhook intoโ React features. useState
is a Hook that lets you add React state to function components.
Example #1
Lets say we have a button that a user could toggle to show/hide specific data. In order to persist the status of this button, we have to use the useState
hook to keep track of the state itself. Let's see the example below:
import {useState} from 'react'
export default function App() {
// Declare a new state variable, which we'll call "isVisible"
// It could be of any type, but here its a Boolean
const [isVisible, setIsVisible] = useState(false)
return (
<>
<button onClick={setIsVisible(prev => !prev)}>Toggle</button>
{isVisible && <div>Hello there my friends, again!!</div>}
</>
)
}
First, when we called the useState hook, we declared a new "state variable". It returns a pair of values: the current state variable, which is in our example isVisible
, and a function that we must use in order to update this value, aka setIsVisible
in our example. The argument we passed to the hook itself is the initial state, which in our example represents a Boolean (false).
Next we hooked our button with a callback function, calling the setIsVisible(prev => !prev)
. Clicking on this button would effectively flip this Boolean value to the opposite of its previous value.
Thus, when a user presses the toggle button for the first time, it changes the isVisible
boolean value from false to true, which results in showing the message <div>Hello there my friends, again!!</div>
. Clicking it again results in hiding the value again as it was originally.
Example #2
Now let's take another example:
import {useState} from 'react'
const Message = ({user}) => {
return (
<h1>User Name: {user.name}</h1>
<h2>User Age: {user.age}<h2>
)
}
export default function App() {
const [user, setUser] = useState({
name: 'Sam',
age: '24'
})
return (
<>
<p>User information:</p>
<Message user={user} >
</div>
)
}
In the above example, In the App component (Parent) we declared a new state variable user
using the useState
hook, while passing the initial state as an object containing some user information (mimicking an object fetched from some auth API). We then called a child component Message
that we 'll create now and passed the user
state variable as a prop. Then we create this Message
child component and destructure the user state variable from the props and consumed it as we want (in our example we just displayed user's name and age in a simple message).
This example is just a very simple and basic presentation on how state variables gets passed from a parent component to its child, which relates to prop-drilling. Whilst we should always keep in mind that this flow of data is always downwards, which means we simply can't declare a state variable in a child component and consume it in the parent, but its the other way around.
Downside of prop-drilling
Throughout a more complex development environment, sometimes simple prop-drilling of some state may create complexity to our work-flow. The reason is what if we need to consume a certain state variable not in a child directly, but rather in a deeper nested child. We'll need to tweak our code and find a better way of consuming state coming from a grand ancestor (grandparent). This is exactly where state management libraries come in hand. In the following parts of this blog series, we'll take a look at my implementations when dealing with global state management.
Final thoughts
State management is mandatory in any web development architecture, thus mastering your way through the best practices and ways of dealing with state management is a huge boost to your web development career, so please make sure to read the next upcoming parts of this blog series.
I'm constantly writing new blog posts where I share my expertise & skills in topics related to web development. If you're interested in such topics to boost your development career, consider following me! ๐ Or visit my personal website!
Thanks for reading, Ciao! ๐