π React API Integration & Data Fetching β Best Practices & Patterns (2025 Guide)
π§² Introduction β Why API Integration Matters in React
Modern React.js applications often rely on external APIs to retrieve and display dataβfrom user profiles and products to real-time dashboards and search results. Effective API integration is crucial for performance, UX, and data consistency.
React offers multiple ways to fetch data, including:
- π Native
fetchAPI oraxios - β
useEffectwithuseStateoruseReducer - π οΈ Libraries like SWR, React Query, and RTK Query
π― In this guide, youβll learn:
- How to fetch data in React using built-in hooks
- Handle loading, error, and success states
- Compare common API libraries
- Structure reusable data-fetching logic
βοΈ 1. Basic API Fetching with useEffect & fetch
import { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => {
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
})
.then(data => setUsers(data))
.catch(setError)
.finally(() => setLoading(false));
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
β
Handles loading and error
β
Uses useEffect for side effect
π Best for simple API needs
π¦ 2. Axios vs Fetch β Which to Use?
| Feature | fetch (built-in) | axios (library) |
|---|---|---|
| Default | Included in browsers | Requires installation |
| JSON parsing | Manual .json() | Automatic |
| Error handling | Manual | Built-in |
| Interceptors | β No | β Yes |
| Cancel requests | β³οΈ With AbortController | β Axios Cancel Token |
npm install axios
π 3. Custom Hook for Reusable Data Fetching
β
useFetch.js
import { useState, useEffect } from 'react';
export function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(setData)
.catch(err => {
if (err.name !== 'AbortError') setError(err);
})
.finally(() => setLoading(false));
return () => controller.abort();
}, [url]);
return { data, loading, error };
}
π Abstracts loading, cleanup, and cancellation logic
β
Great for reusability
π 4. React Query β Powerful Async State
npm install @tanstack/react-query
β Setup:
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
β Usage:
import { useQuery } from '@tanstack/react-query';
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then(res => res.json())
});
β
Built-in caching, refetching, retries, and pagination
β
Works well with mutations (useMutation)
β
Ideal for dashboards and large apps
π οΈ 5. RTK Query β Redux Toolkitβs Data Layer
npm install @reduxjs/toolkit react-redux
β API Slice Example:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const userApi = createApi({
reducerPath: 'userApi',
baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
endpoints: (builder) => ({
getUsers: builder.query({
query: () => 'users',
}),
}),
});
export const { useGetUsersQuery } = userApi;
β Usage in Component:
const { data, isLoading, error } = useGetUsersQuery();
β
Pairs with Redux store
β
Auto-generates hooks
β
Built-in caching, polling, and optimistic updates
π Best Practices
β
Use AbortController for manual fetch cleanup
β
Handle loading and error states gracefully
β
Use React Query or RTK Query for data-heavy apps
β
Avoid fetching in render logic (use useEffect instead)
β
Cache data when appropriate to reduce API calls
π Summary β Recap & Next Steps
Data fetching is a critical part of modern React applications. Whether you choose to use fetch, axios, or advanced tools like React Query and RTK Query, the key is to handle loading, error, and cleanup properly.
π Key Takeaways:
- Use
useEffectfor basic fetching - Use custom hooks to DRY your code
- Axios simplifies requests and adds more features
- React Query and RTK Query manage async state like a pro
- Always manage cleanup and dependencies carefully
βοΈ Real-World Relevance:
Used in apps like GitHub, Notion, Trello, and Stripe to fetch user data, paginate APIs, and sync data in real time.
β FAQ Section
β Should I use fetch or axios?
β
Use fetch for basic needs, and axios for more complex setups (interceptors, token injection, error handling).
β Whatβs the benefit of React Query over useEffect + fetch?
β
React Query handles caching, retries, background refetching, and stale data automatically.
β Is useEffect the best place to fetch data?
β
Yes, for simple APIs. For complex data flows, prefer libraries like React Query or RTK Query.
β Do I need Redux if I use React Query?
β Not necessarily. React Query can replace Redux for many async use cases.
β Can I cancel API requests in React?
β
Yes, using AbortController with fetch or CancelToken in Axios.
Share Now :
