DEV Community

Cover image for Understanding React, Component Lifecycle, and UseEffect Hook
Ugwuoke Adaeze
Ugwuoke Adaeze

Posted on • Edited on

Understanding React, Component Lifecycle, and UseEffect Hook

You may have heard that React is a library but what actually makes it a library and not a framework?
A framework typically provides everything you need to build an application; state management, routing, testing etc.
A library on the other hand focuses on the User Interface and gives you the freedom to use extra tools to complete your project such as redux or context for state management, react-router for routing, and so on, which is exactly what react does.

  • React is a javascript library that uses custom reusable components to make building UIs faster and well structured. This reusability gives you the ability to update a particular section of your application without needing to update it individually everywhere else.
  • React allows developers write both logic and structure on the same page using JSX syntax, making codes easier to read and work with.
  • React uses a Virtual DOM (an in-memory representation of the actual DOM) to update the UI efficiently. When data changes, React updates only the part of the UI that changed, instead of reloading the whole page.

Component Lifecycle in React

In class-based React components, certain methods are invoked at different points in the component’s "lifecycle." These lifecycle methods allow you to control what actions the component should perform at each stage, such as when it mounts, updates, or unmounts.
They are a way of telling your code when to perform a particular action at each stage. The names easily explain the stage each of them represents.

Component DidMount
This method runs once right after the component is rendered for the first time, ie immediately after the component is added to the DOM. It performS any action that should only happen when the component appears for the first time. Usage includes; Fetching data from APIs, setting timers or intervals, adding event listeners etc.
Example Usage
Fetching data from an API when the component loads:

class UserProfile extends React.Component {
  state = { user: null };

  componentDidMount() {
    fetch('https://api.frontendfirefighter.com/user/1')
      .then((response) => response.json())
      .then((data) => this.setState({ user: data }));
  }

  render() {
    const { user } = this.state;
    return <div>{user ? <h1>{user.name}</h1> : <p>Loading...</p>}</div>;
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, componentDidMount() triggers an API call to fetch user data as soon as the component appears.

Component DidUpdate
This method runs every time the component updates, that is whenever props or state change. It’s useful when you need to react to changes in props or states and perform some action after the re-render. Usage includes; Fetching new data if certain props have changed, updating the DOM in response to new data, triggering side effects based on state or prop changes.
Example usage:
Re-fetching data when a prop changes:

class UserProfile extends React.Component {
  componentDidUpdate(prevProps) {
    if (this.props.userId !== prevProps.userId) {
      fetch(`https://api.frontendfirefighter.com/user/${this.props.userId}`)
        .then((response) => response.json())
        .then((data) => console.log('New user data:', data));
    }
  }

  render() {
    return <h1>User ID: {this.props.userId}</h1>;
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, componentDidUpdate() checks if the userId prop has changed. If it has, it fetches new user data.

Component WillUnmount
This method runs just before the component is removed from the DOM. It’s essential for cleaning up resources to avoid memory leaks, such as clearing timers or removing event listeners. It runs right before the component is unmounted and removed from the DOM. Usage includes; clearing timers or intervals, removing event listeners, canceling network requests.
Example Usage:
Clearing an interval when the component unmounts:

class Timer extends React.Component {
  componentDidMount() {
    this.timer = setInterval(() => {
      console.log('Timer running...');
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);  // Cleanup the interval
    console.log('Timer stopped!');
  }

  render() {
    return <h1>Timer Running</h1>;
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, componentWillUnmount() clears the interval to prevent it from running after the component is removed from the screen.

With the pivot towards functional components, react component lifecycle is now managed using the useEffect hook.

useEffect
UseEffect is a react hook that allows you run any side effect or reaction after a component renders, re-renders, or before unmounting.
It takes two parameters;

  • A callback function that contains the reaction or side effect you want to run and
  • A dependency array that controls when it runs.
useEffect(() => {
  // callback function
}, [dependency array]);
Enter fullscreen mode Exit fullscreen mode

No dependencies: The effect runs after every render.
Empty array []: The effect runs only once, like componentDidMount().
Specific dependency (eg [count]): The effect runs only when that state or prop changes.

Component lifecycle with UseEffect

Component didmount

useEffect(() => {
  console.log('I understand useEffect better!');
}, []);  
Enter fullscreen mode Exit fullscreen mode

This will only log on the console once, ie when the component mounts.

Component didupdate

import { useEffect, useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  // This useEffect runs only when 'count' changes
  useEffect(() => {
    console.log(`I read this article ${count} times`);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Read it Again</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Component willunmount

useEffect(() => {
  document.addEventListener('mousedown', handleClickOutside);

  return () => {
    document.removeEventListener('mousedown', handleClickOutside);
  };
}, []);

}
Enter fullscreen mode Exit fullscreen mode

In the above code useEffect adds a mousedown event listener to the document.
The event listener runs whenever a user clicks anywhere on the page. It triggers the handleClickOutside function (In the complete code, it checks if the user clicked outside a modal).

When it happens: The event listener is added right after the component renders, just like componentDidMount.
In class components, componentWillUnmount runs right before the component is removed from the DOM. The cleanup function inside the useEffect serves the same purpose here. Right before the component unmounts, React calls the cleanup function to remove it from the DOM.

Why do we need cleanup?
If we don’t remove the event listener, it will continue to run even after the component is unmounted. This could cause memory leaks or unexpected behavior.

Happy Learning!!!

Top comments (0)