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)
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 & 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);
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