ReactJS - Component Life Cycle Using React Hooks

Hello, aspiring developers! Today, we're going to embark on an exciting journey into the world of ReactJS, focusing on component life cycles using React Hooks. Don't worry if you're new to programming – I'll guide you through each step with clear explanations and plenty of examples. So, let's dive in!

ReactJS - Component Life Cycle Using React Hooks

Introduction to React Hooks

Before we delve into the component life cycle, let's understand what React Hooks are. Imagine Hooks as special tools that allow you to use state and other React features without writing a class. They're like magic wands that give your functional components superpowers!

Why Hooks?

In the old days (well, not that old, but in tech years), we had to use class components to manage state and side effects. But classes can be confusing, especially for beginners. Hooks simplify this process, making our code cleaner and more reusable.

The Component Life Cycle

Just like us humans, React components have a life cycle. They're born (mounted), they grow and change (update), and eventually, they're no longer needed (unmounted). Understanding this life cycle is crucial for creating efficient React applications.

The Three Phases of a Component's Life

  1. Mounting: The component is being added to the DOM.
  2. Updating: The component is re-rendering due to changes in props or state.
  3. Unmounting: The component is being removed from the DOM.

Now, let's see how we can manage these phases using Hooks!

useState: Managing Component State

The useState Hook is your go-to tool for adding state to functional components. Let's look at an example:

import React, { useState } from 'react';

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

In this example, useState(0) initializes a state variable count with a value of 0. The setCount function allows us to update this state. Every time the button is clicked, setCount(count + 1) is called, incrementing the count and causing the component to re-render.

useEffect: Handling Side Effects

The useEffect Hook is like a Swiss Army knife for managing side effects in your components. It combines the functionality of several lifecycle methods from class components.

import React, { useState, useEffect } from 'react';

function ExampleComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    // This effect runs after every render
    console.log('Component rendered');

    // Simulating an API call
    const fetchData = async () => {
      const response = await fetch('https://api.example.com/data');
      const result = await response.json();
      setData(result);
    };

    fetchData();

    // Cleanup function
    return () => {
      console.log('Component will unmount or re-render');
    };
  }, []); // Empty dependency array means this effect runs only once on mount

  return (
    <div>
      {data ? <p>{data}</p> : <p>Loading...</p>}
    </div>
  );
}

This example demonstrates several key concepts:

  1. The effect runs after the component renders.
  2. We're simulating an API call to fetch data.
  3. The cleanup function (returned by the effect) runs before the component unmounts or before the effect re-runs.
  4. The empty dependency array [] means this effect only runs once when the component mounts.

Custom Hooks: Creating Reusable Logic

One of the most powerful features of Hooks is the ability to create custom Hooks. These allow you to extract component logic into reusable functions. Let's create a custom Hook for handling form inputs:

import { useState } from 'react';

function useInput(initialValue) {
  const [value, setValue] = useState(initialValue);

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return [value, handleChange];
}

// Using the custom Hook
function LoginForm() {
  const [username, handleUsernameChange] = useInput('');
  const [password, handlePasswordChange] = useInput('');

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log(`Logging in with ${username} and ${password}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={handleUsernameChange}
        placeholder="Username"
      />
      <input
        type="password"
        value={password}
        onChange={handlePasswordChange}
        placeholder="Password"
      />
      <button type="submit">Login</button>
    </form>
  );
}

This custom useInput Hook encapsulates the logic for handling form inputs, making our LoginForm component much cleaner and more reusable.

React Children Property (Containment)

The children prop in React allows you to pass components as data to other components, providing a way to create wrapper components. This concept is often referred to as "containment".

function Panel({ children, title }) {
  return (
    <div className="panel">
      <h2>{title}</h2>
      {children}
    </div>
  );
}

function App() {
  return (
    <Panel title="Welcome">
      <p>This is the panel content.</p>
      <button>Click me!</button>
    </Panel>
  );
}

In this example, the Panel component can wrap any content passed to it as children, making it highly reusable.

Conclusion

We've covered a lot of ground today! From understanding the basics of React Hooks to exploring the component life cycle and even creating custom Hooks. Remember, practice makes perfect, so don't be afraid to experiment with these concepts in your own projects.

Here's a quick reference table of the Hooks we've discussed:

Hook Purpose Example
useState Manage component state const [count, setCount] = useState(0);
useEffect Handle side effects useEffect(() => { /* effect */ }, []);
Custom Hooks Create reusable logic const [value, handleChange] = useInput('');

Happy coding, and may the Hooks be with you!

Credits: Image by storyset