Custom Hooks
Custom Hooks are JavaScript functions that allow you to reuse React logic across multiple components. A custom Hook follows two simple rules: it must start with the word use, and it can call other Hooks inside it. Custom Hooks do not render UI; instead, they encapsulate logic such as state management, side effects, or event handling.
The main purpose of custom Hooks is to avoid repeating the same logic in multiple components. Before custom Hooks, logic reuse often required higher-order components or render props, which increased complexity.
Basic example of a custom Hook:
import { useState } from "react";
function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
function toggle() {
setValue(prev => !prev);
}
return [value, toggle];
}
Using the custom Hook in a component:
function ToggleExample() {
const [isOn, toggle] = useToggle();
return (
<button onClick={toggle}>
{isOn ? "ON" : "OFF"}
</button>
);
}
Here, the toggle logic is reusable and cleanly separated from the UI.
Custom Hooks with Side Effects
Custom Hooks can also include side effects using useEffect.
Example:
import { useState, useEffect } from "react";
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
function handleResize() {
setWidth(window.innerWidth);
}
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return width;
}
This Hook can be reused in any component that needs window width information.
Advanced Hooks Overview
Advanced Hooks are Hooks that are typically used for performance optimization, advanced patterns, or low-level component behavior. While not needed in every application, they are important for optimizing and scaling React apps.
useMemo
useMemo is used to memoize expensive calculations so they do not run on every render.
const result = useMemo(() => heavyCalculation(data), [data]);
useCallback
useCallback memoizes functions to prevent unnecessary re-creations, especially when passing callbacks to child components.
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
useLayoutEffect
useLayoutEffect works like useEffect but runs synchronously after DOM updates. It is useful when you need to measure layout or perform DOM manipulations before the browser paints.
useLayoutEffect(() => {
console.log("Layout measured");
}, []);
useDeferredValue and useTransition
These Hooks help manage performance in concurrent rendering scenarios by deferring non-urgent updates and improving UI responsiveness.
Real-World Scenario
In large applications, custom Hooks are used to manage shared logic such as authentication, form handling, data fetching, and feature toggles. Advanced Hooks are applied to optimize rendering performance, prevent unnecessary re-renders, and handle complex UI interactions efficiently.
Important Notes and Best Practices
Custom Hooks should focus on a single responsibility and be well-named. Avoid overusing advanced Hooks unless performance issues actually exist. Keep custom Hooks independent of UI and reusable across components.
In summary, custom Hooks are a powerful way to reuse logic and keep components clean, while advanced Hooks provide tools for optimizing performance and handling complex behaviors in modern React applications.