React provides several built-in Hooks to manage state, lifecycle, and other side effects in functional components. Here are some of the most commonly used ones:
useState
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}
useEffect
import { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => setSeconds(s => s + 1), 1000);
return () => clearInterval(interval); // Cleanup on unmount
}, []); // Empty dependency array → runs once
return <p>Timer: {seconds}s</p>;
}
useMemo
import { useMemo, useState } from "react";
function ExpensiveCalculation({ num }) {
const squaredNumber = useMemo(() => {
console.log("Calculating...");
return num * num;
}, [num]);
return <p>Squared: {squaredNumber}</p>;
}
useCallback
import { useCallback, useState } from "react";
function ButtonComponent({ onClick }) {
return <button onClick={onClick}>Click me</button>;
}
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return (
<div>
<p>Count: {count}</p>
<ButtonComponent onClick={handleClick} />
</div>
);
}
useRef
import { useRef, useEffect } from "react";
function FocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} />;
}
useImperativeHandle
React.forwardRef
.import { useImperativeHandle, useRef, forwardRef } from "react";
const CustomInput = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
const inputRef = useRef();
return <input ref={inputRef} />;
});
function Parent() {
const inputRef = useRef();
return (
<div>
<CustomInput ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus Input</button>
</div>
);
}
useContext
<Consumer>
.import { createContext, useContext } from "react";
const ThemeContext = createContext("light");
function ThemeComponent() {
const theme = useContext(ThemeContext);
return <p>Current theme: {theme}</p>;
}
useReducer
useState
, useful for complex state logic.import { 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: throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
<span>{state.count}</span>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
</div>
);
}
useLayoutEffect
useEffect
, but runs synchronously after DOM mutations.import { useLayoutEffect, useRef } from "react";
function LayoutEffectExample() {
const divRef = useRef();
useLayoutEffect(() => {
divRef.current.style.color = "red";
});
return <div ref={divRef}>This text will be red immediately</div>;
}
useDebugValue
import { useDebugValue, useState } from "react";
function useCustomHook(value) {
useDebugValue(value > 5 ? "Large" : "Small");
return useState(value);
}
Hook | Purpose |
---|---|
useState |
Manages local state |
useEffect |
Handles side effects |
useMemo |
Memoizes expensive computations |
useCallback |
Memoizes functions |
useRef |
Creates mutable references |
useImperativeHandle |
Customizes ref exposure |
useContext |
Accesses Context API values |
useReducer |
Manages complex state logic |
useLayoutEffect |
Runs synchronously after render |
useDebugValue |
Adds debug info for custom hooks |