Lifecycle Methods (Class Components)

Learn about React component lifecycle methods such as `componentDidMount`, `componentDidUpdate`, and `componentWillUnmount`, and how to use them to manage side effects.


Mastering React.js: Build Modern Web Applications

React Hooks: A Deep Dive

What are React Hooks?

React Hooks are functions that let you "hook into" React state and lifecycle features from function components. Before Hooks, these features were only available in class components. Hooks don't work inside classes — they let you use React without classes.

Introduced in React 16.8, Hooks revolutionized the way we write React components, making functional components more powerful and easier to manage. They promote code reusability and improve component readability.

Why Use React Hooks?

  • Reusability: Extract stateful logic from a component so it can be tested independently and reused.
  • Readability: Complex components become easier to read and understand.
  • Testability: Functional components with Hooks are generally easier to test.
  • Simplified Component Logic: Reduces the boilerplate often associated with class components.

Introduction to Basic React Hooks

useState Hook

The useState Hook lets you add React state to function components. It's a way to declare state variables within a functional component.

Syntax: const [stateVariable, setStateFunction] = useState(initialValue);

stateVariable: The current state value. setStateFunction: A function that updates the state value. Calling this function re-renders the component with the new state. initialValue: The initial value of the state.

Usage Example:

 import React, { useState } from 'react';

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
}

export default Counter; 

In this example, count is the state variable, and setCount is the function to update it. Each click on the buttons will trigger a re-render with the updated count.

useEffect Hook

The useEffect Hook lets you perform side effects in function components. Side effects are actions that affect things outside of the component, such as fetching data, directly manipulating the DOM, or setting up subscriptions.

Syntax: useEffect(() => { /* Your side effect logic here */ }, [dependencies]);

The first argument is a function containing the side effect logic. The second argument is an optional array of dependencies. If any of the dependencies change, the side effect function will be re-executed. If the array is empty ([]), the effect will only run once after the initial render (like componentDidMount in class components). If the dependency array is omitted, the effect runs after *every* render.

Usage Example:

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

function DataFetcher() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); // Replace with your API endpoint
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    }

    fetchData();
  }, []); // Empty dependency array means this effect runs only once, on mount.

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!data) return <p>No data to display.</p>;

  return (
    <div>
      <h2>Data from API:</h2>
      <p>Title: {data.title}</p>
    </div>
  );
}

export default DataFetcher; 

This example fetches data from an API when the component mounts. The empty dependency array ensures that the effect only runs once. Loading and error states are handled to provide a better user experience.

useContext Hook

The useContext Hook allows you to consume values from a React context without using a render prop or a Consumer component. It simplifies accessing context values in functional components.

Syntax: const contextValue = useContext(Context);

Context: The React Context object you want to consume. This is the object created with React.createContext(). contextValue: The current value of the context.

Usage Example:

 import React, { createContext, useContext, useState } from 'react';

// Create a Context
const ThemeContext = createContext();

function App() {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <div className={`App ${theme}`}>
        <Header />
        <MainContent />
        <button onClick={toggleTheme}>Toggle Theme</button>
      </div>
    </ThemeContext.Provider>
  );
}

function Header() {
  const { theme } = useContext(ThemeContext);

  return (
    <header>
      <h1>My Website ({theme} Theme)</h1>
    </header>
  );
}

function MainContent() {
  const { theme } = useContext(ThemeContext);

  return (
    <main>
      <p>This is the main content of the website.  The theme is currently: {theme}</p>
    </main>
  );
}


export default App; 

In this example, we create a ThemeContext and provide a theme and toggleTheme function as its value. The Header and MainContent components use useContext to access the current theme value and display it. The button in the App component allows toggling the theme, which updates the context and re-renders the consuming components.