DEV Community

Michael Tanaka
Michael Tanaka

Posted on

Deepening Our Grasp on React: State, Context, and Effects

Introduction

I recently had to relearn how to use React for my final project at Flatiron School. It was a bit difficult at first but once I got into it, it was smooth sailing. Felt like I should make this blog post because in case I need to revisit React after a while, I can always remember the basics.

React

React is a powerful library for building dynamic web applications. But like any tool, its true strength is unlocked when you understand its core features deeply. Today, let's dive deeper into three of React's fundamental concepts: state, context, and effects.

Understanding State in React

State is the heartbeat of a React application. It is the mechanism by which we store and manage dynamic data within our components. Let's unpack this.

A. What is State?

At its core, state is data that changes over time and affects your component's output.

B. Using the useState Hook

Introduced in React 16.8, the useState hook provides a way to use state in functional components:

const [count, setCount] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Here:

  • count is the current state value.
  • setCount is the function dedicated to updating this state.

C. Key Insights on State

Immutability: Direct modification of the state is a strict no-go. Always leverage the designated state updating function, like setCount.

// This is wrong
count = count + 1;

// This is correct
setCount(prevCount => prevCount + 1);
Enter fullscreen mode Exit fullscreen mode

Asynchronous Nature: State updates can be asynchronous. When the new state depends on the previous one, always use a functional approach:

setCount(prevCount => prevCount + 1);
Enter fullscreen mode Exit fullscreen mode

Embracing the Power of Context

The React context API is designed to share data that can be considered “global” for a tree of React components.

A. What is Context?

Since I haven't worked with React in a while, I had a problem that consisted of "prop drilling". Prop drilling is where you pass data from a parent to its child component and then to the child's child, and so forth. Context offers a way out.

B. Context Implementation

Here's a basic example illustrating how to implement context:

import React, { createContext, useState } from "react";

export const UserContext = createContext();

export const UserProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [errors, setErrors] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [content, setContent] = useState([]);
  const value = {
    user,
    setUser,
    errors,
    setErrors,
    isLoading,
    setIsLoading,
    content,
    setContent,
  };

  return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};
Enter fullscreen mode Exit fullscreen mode

This was taken from my last project. After doing some research on the topic, the way I used it might not have been the best. I should have created different contexts for different actions. However, since it was a relatively small application, this approach sufficed. Essentially, any of the values passed into the UserContext.Provider as props become available to whatever component you wrap the UserContext.Provider around. AVOID PROP DRILLING AT ALL COSTS. It's a pain to work backwards to undo it all. Believe me!

C. Points to Remember

  • Use Sparingly: Context is best suited for data like user authentication status or application themes — data that's pervasive.
  • Performance Implications: Changing context can cause components consuming it to re-render. Avoid excessive changes to maintain good performance.

Managing Side Effects with useEffect

React components can perform actions known as "side effects", which can affect components in ways beyond just rendering.

A. What is a Side Effect?

In the context of React, a side effect might be a network request, manual DOM manipulation, or attaching event listeners — essentially anything that interacts with the world outside of the component.

B. Illustrating useEffect

React gives us the useEffect hook to handle side effects in functional components:

useEffect(() => {
document.title = `Clicked ${count} times`;

return () => {
    console.log('Executing cleanup procedures');
};
}, [count]);
Enter fullscreen mode Exit fullscreen mode

C. Considerations

  • Dependencies: List dependencies in the array to ensure the effect triggers correctly. If the effect only needs to run once, use an empty dependency array: [].
  • useLayoutEffect: While useEffect actions occur post-render,useLayoutEffect is available for actions before the screen updates. However, use it judiciously.

In Summary

React's component-based architecture and powerful hooks system provide developers with an unparalleled ability to build dynamic applications. Looking back at it, I wish I wrote this post before I worked on my project, as I probably wouldn't have had such a difficult time getting back into the swing of things, but better late than never!

Top comments (0)