Advanced React Hooks
Introduction to Advanced React Hooks
React Hooks changed how we write React applications.
Before hooks, developers relied heavily on class components to manage state and lifecycle methods. But with the introduction of hooks in React 16.8, everything became simpler, cleaner, and more reusable.
What are React Hooks?
React Hooks are special functions that let you use state and lifecycle features inside functional components.
What are Advanced React Hooks?
Advanced React Hooks are powerful built-in and custom hooks like useReducer, useContext, useMemo, and useCallback that help manage complex state, optimize performance, and improve code reusability in modern React applications.
These hooks are essential when:
- Your app grows in complexity
- You need better performance
- You want clean and reusable logic
Why Advanced Hooks Matter
Think of basic hooks like useState as a small toolbox.
Advanced hooks?
They are your full professional toolkit.
They help you:
- Manage complex state logic
- Avoid unnecessary re-renders
- Share logic across components
- Build scalable applications
useReducer Hook
What is useReducer?
useReducer is a React hook used for managing complex state logic using a reducer function instead of multiple useState calls.
When to Use
- Global state (theme, user login)
- Avoid prop drilling
- App-wide settings
Analogy
Think of useContext like Wi-Fi:
- Once connected, everyone can access it
- No need to pass cables (props)
Code Example
import React, { createContext, useContext } from "react";
const ThemeContext = createContext("light");
function Child() {
const theme = useContext(ThemeContext);
return <p>Theme: {theme}</p>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
} useContext
What is useContext?
useContext allows you to access shared data across components without passing props manually at every level.
import React, { createContext, useContext, useState } from 'react';
const UserContext = createContext();
function ParentComponent() {
const [user, setUser] = useState({ name: 'John' });
return (
<UserContext.Provider value={user}>
<ChildComponent />
</UserContext.Provider>
);
}
function ChildComponent() {
const user = useContext(UserContext);
return <p>Welcome, {user.name}!</p>;
}
export default ParentComponent;
useMemo: Optimizing Expensive Calculations
The useMemo hook memoizes a computed value to avoid recalculations when dependencies haven’t changed.
Syntax
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Example
import React, { useState, useMemo } from 'react';
function ExpensiveCalculation({ num }) {
const compute = (n) => {
console.log('Computing...');
return n * 2;
};
const memoizedValue = useMemo(() => compute(num), [num]);
return <p>Computed Value: {memoizedValue}</p>;
}
useRef Hook
What is useRef?
useRef is used to store mutable values that do not trigger re-renders when updated.
When to Use
- Access DOM elements
- Store previous values
- Persist data without re-render
Analogy
Think of useRef like a box:
- You can put anything inside
- Changing it won’t refresh UI
Code Example
import React, { useRef } from "react";
function InputFocus() {
const inputRef = useRef();
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={focusInput}>Focus</button>
</>
);
} useMemo Hook
What is useMemo?
useMemo is used to memoize expensive calculations so they are not recomputed on every render.
When to Use
- Heavy computations
- Filtering large lists
- Performance optimization
Analogy
Like saving your work in cache instead of recalculating every time.
Code Example
import React, { useMemo, useState } from "react";
function ExpensiveComponent() {
const [count, setCount] = useState(0);
const expensiveCalculation = useMemo(() => {
console.log("Calculating...");
return count * 2;
}, [count]);
return (
<div>
<p>{expensiveCalculation}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
</div>
);
} useCallback Hook
What is useCallback?
useCallback returns a memoized function so it doesn’t get recreated on every render.
When to Use
- Passing functions to child components
- Prevent unnecessary re-renders
Analogy
Think of it like saving a function instead of recreating it again and again.
Code Example
import React, { useCallback, useState } from "react";
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
return <Child onClick={handleClick} />;
}
function Child({ onClick }) {
return <button onClick={onClick}>Click Me</button>;
} useLayoutEffect Hook
What is useLayoutEffect?
useLayoutEffect runs synchronously after DOM updates but before the browser paints.
When to Use
- Measuring DOM elements
- Avoiding UI flicker
- Layout calculations
Code Example
import React, { useLayoutEffect, useRef } from "react";
function LayoutExample() {
const boxRef = useRef();
useLayoutEffect(() => {
console.log(boxRef.current.getBoundingClientRect());
}, []);
return <div ref={boxRef}>Box</div>;
} Custom Hooks
What are Custom Hooks?
Custom Hooks are reusable functions that encapsulate logic using other React hooks.
Analogy
Like creating your own mini tool from existing tools.
Example
import { useState } from "react";
function useCounter() {
const [count, setCount] = useState(0);
const increment = () => setCount(c => c + 1);
return { count, increment };
} Real-World Example (Combining Hooks)
import React, { useState, useMemo, useCallback } from "react";
function SearchApp() {
const [query, setQuery] = useState("");
const data = ["React", "Angular", "Vue"];
const filtered = useMemo(() => {
return data.filter(item => item.toLowerCase().includes(query));
}, [query]);
const handleChange = useCallback((e) => {
setQuery(e.target.value);
}, []);
return (
<div>
<input onChange={handleChange} />
{filtered.map(item => <p key={item}>{item}</p>)}
</div>
);
} Performance Optimization Tips
Memoization
- Use
useMemofor values - Use
useCallbackfor functions
Avoid Re-Renders
- Use
React.memo - Stable references
Efficient State Management
- Prefer
useReducerfor complex logic
Common Mistakes
- Overusing
useMemo/useCallback - Missing dependency arrays
- Misusing
useContextfor frequent updates - Not extracting custom hooks
Best Practices for Advanced Hooks
- Keep Dependencies Accurate: Always include dependencies for
useMemoanduseCallback. - Avoid Overuse: Use hooks like
useMemoanduseCallbackonly when performance issues arise. - Abstract Logic: Use Custom Hooks for cleaner, reusable code.
- Combine Hooks Thoughtfully: Leverage multiple hooks for complex scenarios.
FAQs
1. What are Advanced React Hooks?
Advanced React Hooks are hooks like useReducer, useMemo, and useCallback used for complex state and performance optimization.
2. When should I use useReducer instead of useState?
Use it when state logic becomes complex or involves multiple related values.
3. Is useMemo always needed?
No, only for expensive computations.
4. Difference between useMemo and useCallback?
- useMemo → returns value
- useCallback → returns function
5. Are custom hooks necessary?
Yes, for reusable logic and cleaner code.