React Hooks
Understanding React Hooks
React Hooks revolutionized the way developers interact with state and lifecycle methods inside functional components. Introduced in React 16.8, Hooks allow you to perform logic without relying on class components. They make functional components more powerful and enable better code organization.
Why Use Hooks?
- Encapsulation of logic : Reusable stateful logic without modifying component structures.
- Simplified state management : No need for class components or this keyword.
- Better code organization : Makes components more readable and modular.
Essential Hooks and Their Usage
1. useState – Managing Component State
The useState Hook introduces local state within a functional component.
Syntax:
const [stateVariable, setStateFunction] = useState(initialValue);
Example:
import React, { useState } from "react"; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Current Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); } export default Counter;
This example maintains a count state and updates it on button clicks
2. useEffect– Handling Side Effects
useEffect enables side effects such as fetching data, interacting with APIs, and DOM manipulations.
Syntax:
useEffect(() => { // Effect logic here return () => { // Cleanup logic (optional) }; }, [dependencyArray]);
Example:
import React, { useState, useEffect } from "react"; function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const interval = setInterval(() => { setSeconds((prev) => prev + 1); }, 1000); return () => clearInterval(interval); }, []); return <p>Time Elapsed: {seconds}s </p>; } export default Timer;
This effect runs an interval every second and cleans up on unmounting.
3. useContext – Simplified Context API Access
useContext fetches values from React.createContext() without using <Consumer> wrappers.
Syntax:
useEffect(() => { // Effect logic here return () => { // Cleanup logic (optional) }; }, [dependencyArray]);
Example:
import React, { useContext, createContext } from "react"; const ThemeContext = createContext("light"); function ThemeComponent() { const theme = useContext(ThemeContext); return <p>Current Theme: {theme}</p>; } export default function App() { return ( <ThemeContext.Provider value="dark"> <ThemeContext /> <ThemeContext.Provider> ); }
This demonstrates how to retrieve and apply theme data using useContext.
4. useReducer – Advanced State Logic
Acts as an alternative to useState when handling complex state transitions.
Syntax:
const [state, dispatch] = useReducer(reducerFunction, initialState);
Example:
import React, { useReducer } from "react"; const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case "increment": return { count: state.count + 1 }; case "decrement": return { count: state.count - 1 }; default: return state; } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>Count: {state.count}<p> <button onClick={() => dispatch({ type: "increment" })}>+</button> <button onClick={() => dispatch({ type: "decrement" })}>-</button> </div> ); } export default Counter;
This example structures state updates using a reducer function and an action dispatcher.
5. useRef – Accessing DOM Elements & Persisting Values
useRef creates a reference object that persists across renders without causing re-renders.
Syntax:
const refContainer = useRef(initialValue);
Example:
import React, { useRef, useEffect } from "react"; function FocusInput() { const inputRef = useRef(null); useEffect(() => { inputRef.current.focus(); }, []); return <input ref={inputRef} placeholder="Focus on me!" />; } export default FocusInput;
This ensures an input field gains focus automatically when the component mounts.
6. useMemo – Optimizing Performance
useMemo prevents unnecessary calculations by memoizing values.
Syntax:
const memoizedValue = useMemo(() => computeExpensiveValue(dep), [dep]);
Example:
import React, { useState, useMemo } from "react"; function ExpensiveCalculation({ num }) { const squared = useMemo(() => { console.log("Computing square..."); return num * num; }, [num]); return <p>Square: {squared}</p>; } export default function App() { const [count, setCount] = useState(2); return ( <div> <ExpensiveCalculation num={count} /> <button onClick={() => setCount(count + 1)}>Increase</button> </div> ); }
Only recalculates when num changes, avoiding redundant calculations.
7. useCallback – Memoizing Functions
useCallback optimizes performance by memoizing function references.
Syntax:
const memoizedCallback = useCallback(() => { // Function logic }, [dependencies]);
Example:
import React, { useState, useCallback } from "react"; function Button({ onClick }) { return <button onClick={onClick}>Click Me</button>; } export default function App() { const [count, setCount] = useState(0); const handleClick = useCallback(() => setCount((c) => c + 1), []); return ( <div> <p>Count: {count}</p> <Button onClick={handleClick} /> </div> ); }
Prevents unnecessary re-creations of handleClick when rendering.
Conclusion
React Hooks empower functional components with capabilities previously limited to class-based components. They simplify state management, optimize performance, and promote reusable logic. Mastering these Hooks enhances the development experience and leads to more maintainable applications.