Design Converter
Education
Last updated on Feb 25, 2025
•5 mins read
Last updated on Feb 25, 2025
•5 mins read
Software Development Executive - II
I know who I am.
What makes React Hooks so useful?
They let you manage state and side effects in functional components without extra complexity. React Hooks types help you write cleaner and more readable code.
This blog breaks down different hooks, their uses, and best practices. You'll also learn how to keep your components fast and maintainable.
Let's get started!
React Hooks allows developers to manage state and lifecycle methods within functional components. Before hooks, stateful logic was only possible using class components. Now, hooks make it easier to manage local state, fetch data, and encapsulate reusable logic in a structured manner.
React Hooks can be divided into two categories: built-in hooks and custom hooks. Built-in hooks provide direct functionality, while custom hooks encapsulate reusable logic for better code modularity.
Built-in hooks provide fundamental functionalities for managing state, side effects, and context.
Within functional components, the useState hook aids in local state management. The state variable and an update function are included in the array that is returned.
Example: Using useState for Counter Management
1import { useState } from "react"; 2 3function Counter() { 4 const [count, setCount] = useState(0); 5 6 return ( 7 <div> 8 <p>Count: {count}</p> 9 <button onClick={() => setCount(count + 1)}>Increment</button> 10 </div> 11 ); 12}
This hook is useful for managing component-level state, such as form inputs or UI toggles.
The useEffect hook is used for executing side effects, such as fetching data, subscriptions, and manually manipulating the DOM.
Example: Fetching Data with useEffect
1import { useState, useEffect } from "react"; 2 3function DataFetcher() { 4 const [data, setData] = useState(null); 5 6 useEffect(() => { 7 fetch("https://jsonplaceholder.typicode.com/posts") 8 .then((response) => response.json()) 9 .then((data) => setData(data)); 10 }, []); // Empty dependency array ensures this runs only when the component mounts 11 12 return <pre>{JSON.stringify(data, null, 2)}</pre>; 13}
The dependency array ensures that the effect runs at the right time.
The useContext hook simplifies global state management within a component tree.
Example: Using useContext with Theme Context
1import { useContext } from "react"; 2import { ThemeContext } from "./ThemeProvider"; 3 4function ThemedButton() { 5 const theme = useContext(ThemeContext); 6 return <button style={{ background: theme }}>Themed Button</button>; 7}
This approach helps share a context value like themes or user authentication across multiple components.
When state logic becomes complex, useReducer is a better choice than useState. It uses a reducer function to determine state transitions.
Example: Using useReducer for Counter
1import { useReducer } from "react"; 2 3function reducer(state, action) { 4 switch (action.type) { 5 case "increment": 6 return { count: state.count + 1 }; 7 case "case decrement": 8 return { count: state.count - 1 }; 9 default: 10 throw new Error("new error: Invalid action type"); 11 } 12} 13 14function Counter() { 15 const [state, dispatch] = useReducer(reducer, { count: 0 }); 16 17 return ( 18 <div> 19 <p>Count: {state.count}</p> 20 <button onClick={() => dispatch({ type: "increment" })}>+</button> 21 <button onClick={() => dispatch({ type: "case decrement" })}>-</button> 22 </div> 23 ); 24}
This approach is useful for managing complex state logic, especially in large applications.
Custom hooks help encapsulate reusable logic while keeping functional components clean.
A custom hook can be used to handle repetitive logic such as fetching data.
Example: useFetch Custom Hook
1import { useState, useEffect } from "react"; 2 3function useFetch(url) { 4 const [data, setData] = useState(null); 5 const [loading, setLoading] = useState(true); 6 7 useEffect(() => { 8 async function fetchData() { 9 try { 10 const response = await fetch(url); 11 const result = await response.json(); 12 setData(result); 13 } catch (error) { 14 console.error("new error: Failed to fetch data", error); 15 } finally { 16 setLoading(false); 17 } 18 } 19 fetchData(); 20 }, [url]); 21 22 return { data, loading }; 23} 24 25export default useFetch;
This custom hook allows components to fetch data without duplicating logic.
1import useFetch from "./useFetch"; 2 3function PostList() { 4 const { data, loading } = useFetch( 5 "https://jsonplaceholder.typicode.com/posts" 6 ); 7 8 if (loading) return <p>Loading...</p>; 9 10 return ( 11 <ul> 12 {data.map((post) => ( 13 <li key={post.id}>{post.title}</li> 14 ))} 15 </ul> 16 ); 17}
By using own custom hooks, developers can simplify existing components and improve maintainability.
React provides hooks like useCallback and useMemo to enhance performance by reducing re-render cycles.
A callback function inside a component is recreated on each render. useCallback ensures that the function reference remains the same unless dependencies change.
Example: Using useCallback
1import { useState, useCallback } from "react"; 2 3function ParentComponent() { 4 const [count, setCount] = useState(0); 5 6 const increment = useCallback(() => { 7 setCount((prevCount) => prevCount + 1); 8 }, []); 9 10 return <ChildComponent increment={increment} />; 11}
This prevents unnecessary re-renders of the child component.
useMemo optimizes performance by caching computed values.
Example: Optimizing Performance with useMemo
1import { useState, useMemo } from "react"; 2 3function ExpensiveCalculation({ number }) { 4 const squaredNumber = useMemo(() => { 5 return number * number; 6 }, [number]); // Runs only when "number" changes 7 8 return <p>Squared Number: {squaredNumber}</p>; 9}
This approach is useful in complex components where expensive calculations can slow down performance.
React Hooks replace traditional lifecycle methods such as componentDidMount. The useEffect hook runs logic when a component mounts.
Example: Logging When a Component Mounts
1import { useEffect } from "react"; 2 3function Logger() { 4 useEffect(() => { 5 console.log("Component has mounted"); 6 7 return () => { 8 console.log("Component unmounted"); 9 }; 10 }, []); // Runs only when the component mounts 11 12 return <p>Check the console</p>; 13}
This pattern is useful for tracking re-render behavior in React function components.
Understanding React Hooks Types is key to developing efficient functional components. Built-in hooks simplify common tasks, while custom hooks help encapsulate reusable logic. Optimizing performance with useCallback and useMemo minimizes unnecessary re-render cycles. Using hooks effectively leads to cleaner, more maintainable React applications.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.