Understanding React Hooks

In the early days of React, functional components were not efficient. If you needed state or lifecycle methods, you had to refactor to a Class component. Then, hooks arrived, and everything changed.
Today, we’re diving deep into the six most essential hooks that will turn you into a React pro.
1. useState: The Heartbeat of Your Component
The useState hook allows functional components to maintain a local state. When the state changes, React automatically re-renders the component to reflect the new data.
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Current Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
Always use the functional update setCount(prev => prev + 1) if your new state depends on the previous one to avoid stale closures.
2. useEffect: Managing Side Effects
useEffect is your go-to for anything that happens outside the scope of the component’s return, like API calls, subscriptions, or manual DOM updates.
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
setData(data);
};
fetchData();
}, []); // Empty array means this runs once on mount
3. useRef: Keep a Value Without Re-render
useRef returns a mutable ref object. It’s unique because changing the .current property does not trigger a re-render. Use it to access DOM elements or store persistent values.
const TextInputWithFocusButton = () => {
const inputEl = useRef(null);
const onButtonClick = () => {
// Accessing the DOM directly
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
};
4. useMemo: Avoid Repeating Heavy Work
Computing expensive values on every render can lag your app. useMemo caches (memoizes) the result of a calculation and only re-calculates it when dependencies change.
const expensiveResult = useMemo(() => {
return performHeavyCalculation(data);
}, [data]); // Only re-runs if 'data' changes
5. useCallback: Memoizing Functions
While useMemo caches a value, useCallback caches a function instance. This is crucial when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary re-renders.
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
6. useContext: Share Data Across Components
Tired of passing data through five layers of components? useContext allows you to share data directly to the components that need it.
const ThemeContext = React.createContext('light');
const Display = () => {
const theme = useContext(ThemeContext);
return <div className={theme}>The current theme is {theme}</div>;
};
Finally
Don’t use all hooks everywhere.
Start with
useStateanduseEffectUse
useMemoanduseCallbackonly when neededKeep things simple first



