Introduction to React Hooks: Modern State & Lifecycle Management in Functional Components

Last updated 2 months, 2 weeks ago | 123 views 75     5

Tags:- React

Introduction: Why React Hooks Matter

Prior to React 16.8, developers had to rely on class components to manage state and lifecycle methods. This created unnecessary complexity, boilerplate code, and limited reusability.

React Hooks revolutionized the way developers write components by allowing stateful logic and side effects directly inside functional components—making your code simpler, cleaner, and more reusable.

With hooks, you can:

  • Use state in functional components

  • Perform side effects

  • Reuse logic with custom hooks

  • Avoid complex class syntax

Let’s dive into the essential hooks every React developer should know.


What Are React Hooks?

React Hooks are special functions that let you "hook into" React features such as state, context, and lifecycle from within functional components.

Key Rules of Hooks:

  • Hooks must be called at the top level of your component.

  • Hooks must be called from React functions, not regular JS functions.

  • Hooks are not used in class components.


Core React Hooks and How to Use Them

1️⃣ useState() — For Managing Local Component State

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // Declare a state variable

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click Me</button>
    </div>
  );
}
  • useState() returns a state value and a setter function.

  • Calling the setter (e.g., setCount) triggers a re-render.


2️⃣ useEffect() — For Side Effects (API Calls, Subscriptions)

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

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prev => prev + 1); // increment seconds
    }, 1000);

    return () => clearInterval(interval); // cleanup on unmount
  }, []); // empty dependency array = run once on mount

  return <p>Timer: {seconds}s</p>;
}
  • useEffect() runs after render.

  • You can conditionally run effects based on dependencies.

  • Cleanup is handled via return function.


3️⃣ useContext() — For Global State Using Context API

const ThemeContext = React.createContext();

function ThemedComponent() {
  const theme = React.useContext(ThemeContext); // use context value
  return <div style={{ backgroundColor: theme }}>Themed Box</div>;
}
  • Use with React.createContext() to avoid prop drilling.

  • Best for themes, auth, and other global data.


4️⃣ useRef() — For Referencing DOM or Persisting Values

import { useRef, useEffect } from 'react';

function FocusInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus(); // Auto-focus input on mount
  }, []);

  return <input ref={inputRef} type="text" />;
}
  • useRef() gives you a mutable .current object.

  • Common use cases: accessing DOM elements, keeping previous values, or avoiding re-renders.


✅ Bonus: Custom Hooks

Create your own hook for reusable logic.

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  const increment = () => setCount(c => c + 1);
  const reset = () => setCount(initialValue);

  return { count, increment, reset };
}

Use it like this:

function Counter() {
  const { count, increment, reset } = useCounter(5);

  return (
    <>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
      <button onClick={reset}>Reset</button>
    </>
  );
}

✅ Full Working Example Using Multiple Hooks

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

function App() {
  const [count, setCount] = useState(0);
  const inputRef = useRef(null);

  useEffect(() => {
    document.title = `You clicked ${count} times`; // side effect
  }, [count]);

  useEffect(() => {
    inputRef.current.focus(); // auto-focus on mount
  }, []);

  return (
    <div style={{ padding: 20 }}>
      <h1>React Hooks Example</h1>
      <input ref={inputRef} placeholder="Type here..." />
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(c => c + 1)}>Click Me</button>
    </div>
  );
}

export default App;

⚠️ Tips & Common Pitfalls

✅ Best Practices

  • Always define hooks at the top of your function.

  • Use custom hooks for logic reuse.

  • Use multiple useEffect() hooks for separate concerns (not one mega-hook).

  • Prefer useCallback() and useMemo() for performance-sensitive logic.

❌ Common Mistakes

  • Calling hooks inside loops or conditionals → ❌ Hooks must run in the same order on every render.

  • Forgetting dependency arrays in useEffect() → leads to stale data or infinite loops.

  • Overusing useState() for data that could live in context or a store.


Comparison Table: Class vs Hook-Based Component

Feature Class Component Functional Component (Hooks)
State Management this.state, this.setState useState()
Lifecycle componentDidMount, etc. useEffect()
DOM Access createRef() useRef()
Readability Verbose Cleaner and more concise
Code Reuse HOCs, Render Props Custom Hooks

Conclusion: Embrace the Power of Hooks

React Hooks provide a modern, elegant, and efficient way to write components by:

  • Eliminating class boilerplate

  • Encouraging logic reuse

  • Improving readability

Whether you're new to React or refactoring legacy code, Hooks should be your go-to for writing clean, modular, and scalable components.


Key Takeaways:

  • Use useState for local component state.

  • Use useEffect for side effects like API calls and subscriptions.

  • Use useRef, useContext, and custom hooks to unlock advanced functionality.

  • Follow the Rules of Hooks to avoid bugs and unpredictable behavior.