React Hooks Complete Guide

July 1, 2025

🎣 Complete React Hooks Guide with Practical Examples

🧠 useState

What it does: Adds local state to a function component.

Code Example:


import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)>
      You clicked {count} times
    </button>
  );
}
    

Why it's useful: useState is the most basic way to store dynamic data in a React component (e.g., form fields, counters).

⚙️ useReducer

What it does: Handles more complex state logic using reducers.

Code Example:


const 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 (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })>-</button>
    </div>
  );
}
    

Why it's useful: Best for state that changes in multiple ways (e.g., complex forms, undo/redo logic).

🔁 useEffect

What it does: Performs side effects after rendering (like fetching data, DOM updates, subscriptions).

Code Example:


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

Why it's useful: Replaces lifecycle methods like componentDidMount and componentDidUpdate from class components.

📐 useLayoutEffect

What it does: Same as useEffect, but it runs synchronously after all DOM mutations, before the browser paints.

Code Example:


useLayoutEffect(() => {
  console.log("DOM has been updated before paint");
}, []);
    

Why it's useful: Ideal for measuring layout or making visual DOM changes without flickering.

🧵 useInsertionEffect

What it does: Used to inject styles or manipulate CSS-in-JS libraries before the browser layout happens.

Code Example:


useInsertionEffect(() => {
  // Add styles directly before browser layout
}, []);
    

Why it's useful: Rarely needed unless working with styling libraries like Emotion or styled-components.

🌍 useContext

What it does: Accesses context values without needing to pass props manually through components.

Code Example:


const ThemeContext = React.createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>I am styled by theme!</button>;
}
  

Why it's useful: Makes it easier to share global state like themes, authentication, or language settings.

🧭 useRef

What it does: Creates a mutable object that persists across renders and can hold a DOM reference.

Code Example:


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

  const handleClick = () => {
    inputRef.current.focus();
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>Focus the input</button>
    </>
  );
}
  

Why it's useful: Perfect for accessing or modifying DOM elements directly (e.g. focus, scroll).

🔧 useImperativeHandle

What it does: Customizes the instance value exposed when using refs with forwardRef.

Code Example:


const FancyInput = React.forwardRef((props, ref) => {
  const inputRef = useRef();

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

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

Why it's useful: Useful for libraries or components that expose custom imperative APIs.

📦 useMemo

What it does: Memoizes the result of an expensive calculation so it only recalculates when dependencies change.

Code Example:


const expensiveCalculation = (num) => {
  console.log('Calculating...');
  return num * 2;
};

function App({ number }) {
  const result = useMemo(() => expensiveCalculation(number), [number]);
  return <p>Result: {result}</p>;
}
  

Why it's useful: Improves performance by avoiding unnecessary recalculations on every render.

🔁 useCallback

What it does: Returns a memoized version of a callback function that only changes if dependencies change.

Code Example:


const handleClick = useCallback(() => {
  console.log('Clicked!');
}, []);
  

Why it's useful: Helps prevent unnecessary re-renders in child components that receive functions as props.

🚀 useTransition

What it does: Allows you to mark a part of the UI update as non-urgent (transitional), improving responsiveness.

Code Example:


const [isPending, startTransition] = useTransition();

const handleChange = (e) => {
  const input = e.target.value;
  startTransition(() => {
    setSearchTerm(input);
  });
};
  

Why it's useful: Helps keep your app responsive by deferring slow updates during input typing or navigation.

🐢 useDeferredValue

What it does: Defers a value update so the UI can prioritize urgent updates first.

Code Example:


const deferredSearchTerm = useDeferredValue(searchTerm);
const filteredResults = useMemo(() => {
  return items.filter(item => item.includes(deferredSearchTerm));
}, [deferredSearchTerm]);
  

Why it's useful: Improves user experience when filtering large lists or rendering heavy components.

🆔 useId

What it does: Generates unique IDs for accessibility and form elements.

Code Example:


const id = useId();
return (
  <>
    <label htmlFor={id}>Email</label>
    <input id={id} type="email" />
  </>
);
  

Why it's useful: Prevents ID conflicts in forms, especially inside reusable components.

🐞 useDebugValue

What it does: Shows custom labels in React DevTools for your custom hooks.

Code Example:


function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);
  useDebugValue(isOnline ? 'Online' : 'Offline');
  return isOnline;
}
  

Why it's useful: Helps during development by displaying extra debug information in DevTools.

🔄 useSyncExternalStore

What it does: Subscribes to external stores with support for concurrent rendering.

Code Example:


const state = useSyncExternalStore(store.subscribe, store.getSnapshot);
  

Why it's useful: The recommended way to read from external stores (like Redux) in modern React.

🎯 useActionState

What it does: Manages form-like state transitions triggered by user actions (experimental).

Code Example:


const [state, formAction] = useActionState(
  async (prevState, formData) => {
    const res = await submitToServer(formData);
    return res;
  },
  {}
);
  

Why it's useful: Helpful for server-side forms with transitions (experimental in React 18+).

📤 useFormStatus

What it does: Tracks the pending status of a form submission.

Code Example:


const { pending } = useFormStatus();

return (
  <button disabled={pending}>
    {pending ? 'Sending...' : 'Submit'}
  </button>
);
  

Why it's useful: Adds feedback UX during form submits in concurrent rendering mode.

📝 useFormState

What it does: Helps manage state of server-side form submissions.

Code Example:


const [state, formAction] = useFormState(actionFn, initialState);
  

Why it's useful: Part of React’s experimental form features — keeps form logic centralized.

The Ultimate Managed Hosting Platform