< alishour.dev />

React state management - Part 1: Introduction & local state management Preview Image

React state management - Part 1: Introduction & local state management

May 3, 2022

A comprehensive guide to understanding state management in React applications, focusing on local state management techniques and best practices.

React JS
State Management

4 min read

Introduction

When building a website with React, state management is one of the most crucial concepts you'll rely on.

In this series, I'll show you the best practices and techniques for managing state across your applications and websites.

What is React?

Over a decade ago, developers built websites using vanilla JavaScript, which involved writing lots of redundant code and lengthy development processes. The introduction of JavaScript frameworks based on UI components revolutionized web development, making it faster and easier to create modern websites with reusable components. React, created by Facebook, emerged from this evolution and has become the most popular JavaScript framework today.

What is React State Management?

Each React component has a built-in state object where you can store data that persists between component renderings. You can manage component state either locally or through an external state management library.

Local State Management

In this part of the series, we'll explore local state management.

React comes with several useful hooks, with useState() being one of the most essential.

But what exactly is a hook? According to the official docs, it's a special function that lets you "hook into" React features. The useState hook specifically allows you to add state management to function components.

Examples & Implementation

Example 1

Let's say we have a button that toggles specific data on and off. To maintain the button's status, we need to use the useState hook to track its state. Here's an example:

import { useState } from 'react'

function ToggleExample() {
  const [isVisible, setIsVisible] = useState(false)
  
  return (
    <>
      <button onClick={() => setIsVisible(!isVisible)}>
        Toggle
      </button>
      {isVisible && <div>Content is now visible!</div>}
    </>
  )
}

When we call the useState hook, we declare a new "state variable." It returns two values: the current state (isVisible in our example) and a function to update it (setIsVisible). The argument passed to useState is the initial state—in this case, a Boolean value of false.

In our button's onClick handler, we use a callback function that calls setIsVisible(prev => !prev). This toggles the Boolean value to its opposite whenever the button is clicked.

When a user first clicks the toggle button, it changes isVisible from false to true, displaying the message Content is now visible!. A second click hides the message by setting the value back to false.

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 example above, the App component (parent) declares a new state variable user using the useState hook. The initial state is an object containing user information (simulating data fetched from an auth API). We then create a child component Message and pass the user state variable as a prop. The Message component destructs the user data from its props and displays the user's name and age in a simple message.

This example demonstrates how state variables pass from a parent component to its child—a concept related to prop drilling. Remember that this data flow only moves downward: while a parent component can pass state to its children, a child component cannot declare state that will be consumed by its parent.

Prop Drilling Challenges

In more complex applications, simple prop-drilling can complicate our workflow. This happens when we need to pass state not just to direct children, but to deeply nested components. Finding better ways to handle state from distant ancestor components becomes necessary. This is where state management libraries become valuable. In the following parts of this series, I'll demonstrate my approaches to handling global state management.

Conclusion

Understanding local state management is crucial for React development. It forms the foundation for more advanced state management patterns and helps in building more efficient React applications.

💡 Pro Tip: Always start with local state management before considering more complex state management solutions. It's often sufficient for smaller applications and simpler component hierarchies.

let's discuss
your ideas