React Hooks – Complete Beginner-Friendly Guide (with Examples)
React Hooks

React Hooks – Complete Beginner-Friendly Guide (with Examples)

React Hooks allow you to use state and other React features in functional components without writing class components. Introduced in React 16.8, hooks make code cleaner, reusable, and easier to understand.


Why React Hooks?

Before hooks:

  • State and lifecycle methods were only available in class components
  • Code became complex and hard to reuse

With hooks:

  • Use state & lifecycle logic in function components
  • Reuse logic easily
  • Less boilerplate, more readable code


1. useState – Managing State

Why use useState?

To store and update data that changes over time (counter, input value, toggle, etc.)

When to use?

  • When UI needs to update based on data change
  • Forms, counters, toggles, API data

Example: Counter App

import React, { useState } from "react";

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

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

export default Counter;
        

📌 Explanation:

  • count → current state
  • setCount → updates state
  • React re-renders when state changes


2. useEffect – Side Effects

Why use useEffect?

To perform side effects like:

  • API calls
  • Timers
  • Event listeners
  • DOM updates

When to use?

  • Fetching data from an API
  • Running code when component loads or updates

Example: Run Code on Component Load

import React, { useEffect } from "react";

function Example() {
  useEffect(() => {
    console.log("Component Mounted");
  }, []);

  return <h2>Hello React</h2>;
}

export default Example;
        

📌 Explanation:

  • Runs once because dependency array [] is empty
  • Similar to componentDidMount


3. useRef – Accessing DOM or Persisting Values

Why use useRef?

  • Access DOM elements directly
  • Store values without causing re-render

When to use?

  • Focus input fields
  • Store previous values
  • Timers or mutable values

Example: Focus Input on Button Click

import React, { useRef } from "react";

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

  return (
    <div>
      <input ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>
        Focus Input
      </button>
    </div>
  );
}

export default FocusInput;
        

📌 Explanation:

  • useRef gives direct access to DOM
  • Does NOT re-render component


4. useCallback – Optimize Functions

Why use useCallback?

To prevent unnecessary function re-creation, improving performance.

When to use?

  • Passing functions to child components
  • Preventing unnecessary re-renders

Example: Optimized Function

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

function Button({ handleClick }) {
  return <button onClick={handleClick}>Click Me</button>;
}

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

  const increment = useCallback(() => {
    setCount((prev) => prev + 1);
  }, []);

  return (
    <div>
      <h2>{count}</h2>
      <Button handleClick={increment} />
    </div>
  );
}

export default App;
        

📌 Explanation:

  • useCallback memoizes the function
  • Useful when child components depend on function props


5. useMemo – Memoize Values

Why use useMemo?

To avoid expensive calculations on every render.

When to use?

  • Heavy calculations
  • Filtering or sorting large lists
  • Performance optimization

Example

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

function ExpensiveCalc({ num }) {
  const result = useMemo(() => {
    console.log("Calculating...");
    return num * 2;
  }, [num]);

  return <h2>Result: {result}</h2>;
}

export default ExpensiveCalc;
        

📌 Key Point: useMemo caches the value, not the function.


6. useContext – Avoid Prop Drilling

Why use useContext?

To share data globally without passing props manually.

When to use?

  • Theme (dark/light)
  • Auth user data
  • Language settings

Example

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

const ThemeContext = createContext();

function Child() {
  const theme = useContext(ThemeContext);
  return <h2>Theme: {theme}</h2>;
}

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Child />
    </ThemeContext.Provider>
  );
}

export default App;
        

📌 Key Point: useContext replaces unnecessary prop passing.


7. useReducer – Advanced State Logic

Why use useReducer?

For complex state logic with multiple actions.

When to use?

  • Large forms
  • State with multiple conditions
  • Redux-like patterns

Example

import React, { useReducer } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <>
      <h2>{state.count}</h2>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
    </>
  );
}

export default Counter;
        

📌 Key Point: Use useReducer when useState becomes messy.


8. useLayoutEffect – DOM Measurements

Why use useLayoutEffect?

Runs before the browser paints the screen.

When to use?

  • Measure DOM size
  • Animations
  • Layout calculations

Example

import React, { useLayoutEffect, useRef } from "react";

function Box() {
  const boxRef = useRef();

  useLayoutEffect(() => {
    console.log(boxRef.current.offsetWidth);
  }, []);

  return <div ref={boxRef}>Hello</div>;
}

export default Box;
        

⚠️ Use sparingly — useEffect is preferred most of the time.


9. useImperativeHandle – Control Child from Parent

Why use useImperativeHandle?

Expose specific methods from child component.

When to use?

  • Custom input components
  • Controlled focus or reset logic

Example

import React, { useRef, forwardRef, useImperativeHandle } from "react";

const Input = forwardRef((props, ref) => {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focus() {
      inputRef.current.focus();
    }
  }));

  return <input ref={inputRef} />;
});

function App() {
  const ref = useRef();

  return (
    <>
      <Input ref={ref} />
      <button onClick={() => ref.current.focus()}>Focus</button>
    </>
  );
}

export default App;
        

10. useTransition – Smooth UI Updates (React 18)

Why use useTransition?

To keep UI responsive during heavy updates.

When to use?

  • Large lists
  • Search filtering
  • Expensive rendering

Example

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

function App() {
  const [text, setText] = useState("");
  const [isPending, startTransition] = useTransition();

  function handleChange(e) {
    startTransition(() => {
      setText(e.target.value);
    });
  }

  return (
    <>
      <input onChange={handleChange} />
      {isPending && <p>Loading...</p>}
      <p>{text}</p>
    </>
  );
}

export default App;
        

11. useDeferredValue – Delay Updates

Why use useDeferredValue?

Delay non-urgent UI updates.

When to use?

  • Search results
  • Live filtering

Example

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

function Search() {
  const [query, setQuery] = useState("");
  const deferredQuery = useDeferredValue(query);

  return (
    <>
      <input onChange={(e) => setQuery(e.target.value)} />
      <p>Searching for: {deferredQuery}</p>
    </>
  );
}

export default Search;
        

12. useId – Unique IDs (React 18)

Why use useId?

Generate unique IDs for accessibility.

When to use?

  • Forms
  • Labels
  • Server-side rendering

Example

import React, { useId } from "react";

function Form() {
  const id = useId();

  return (
    <>
      <label htmlFor={id}>Email</label>
      <input id={id} />
    </>
  );
}

export default Form;
        
Article content

Final Advice

  • ✅ Start with: useState, useEffect
  • ⚡ Learn performance hooks later: useMemo, useCallback
  • 🧠 Use advanced hooks only when needed

#React #ReactJS #JavaScript #WebDevelopment #FrontendDevelopment

To view or add a comment, sign in

More articles by 🇮🇳 Sachin Ghadi

Others also viewed

Explore content categories