LogIn
I don't have account.

Mastering React Hooks : The Complete Guide

Code Crafter
138 Views

What Are React Hooks?

React Hooks are functions that let you use state and lifecycle features in functional components. Introduced in React 16.8, they eliminated the need for class components for managing state or side effects.

Why Hooks?

Hooks solve long-standing problems in React

  • Sharing logic between components (via custom hooks, not HOCs or render props)
  • Better code organization
  • Simplified components, no need to refactor into class-based components

Commonly Used React Hooks

1. useState – Add State to Functional Components

const [count, setCount] = useState(0);
  • useState(initialValue) returns an array: [state, setState]
  • You can update state with setState(newValue)
Example
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <p>{count}</p>
    </div>
  );
}

2. useEffect – Side Effects in Functional Components

useEffect(() => {
  console.log("Component mounted or updated");
  return () => {
    console.log("Cleanup on unmount or before next effect");
  };
}, [dependencies]);
  • It replaces lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount.
  • Use Cases: Fetching data , Subscribing to events , DOM manipulation etc

3. useContext – Consume Context Easily

const value = useContext(MyContext);
  • Cleaner than the <MyContext.Consumer> pattern
  • Encourages centralized state/shared logic

4. useRef – Persistent Mutable Value

const inputRef = useRef(null);
  • Access DOM nodes
  • Store values that don’t trigger re-renders

5. useMemo &amp; useCallback – Performance Optimization

const memoizedValue = useMemo(() => expensiveComputation(data), [data]);
const memoizedCallback = useCallback(() => handleClick(id), [id]);
  • useMemo(fn, deps) memoizes a value
  • useCallback(fn, deps) memoizes a function

Prevents unnecessary recalculations or re-creations on re-renders

6. useReducer – Manage Complex State

A better alternative to useState when the state logic is complex or involves multiple sub-values.

const [state, dispatch] = useReducer(reducer, initialState);
    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;
      }
    };
    
    const [state, dispatch] = useReducer(reducer, { count: 0 });

    Custom Hooks – Reusable Logic

    Custom hooks allow you to extract and reuse stateful logic.

    function useWindowWidth() {
      const [width, setWidth] = useState(window.innerWidth);
    
      useEffect(() => {
        const handleResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
      }, []);
    
      return width;
    }

    Use like this

    const width = useWindowWidth();

    Best Practices with Hooks

    • Always call hooks at the top level (not inside loops or conditions)
    • Only call hooks from React functions or other hooks
    • Use ESLint plugin: eslint-plugin-react-hooks
    • Break complex logic into custom hooks
    • Memoize expensive operations with useMemo
    • Avoid overusing useEffect as a catch-all for logic

    When Not to Use Hooks

    • When using class components (not compatible)
    • If the shared logic belongs in Redux, Recoil, or Jotai, prefer those for global state
    • When over-abstracting – avoid turning everything into a custom hook