Stop Struggling With Data Fetching in React (React Day 7)
Source: Dev.to
Fetch Basics
The native fetch API is built into browsers and works with promises.
fetch('https://api.example.com/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
Axios Overview
Axios is a popular HTTP client that adds conveniences such as automatic JSON parsing, better error handling, request cancellation, and interceptors.
import axios from 'axios';
axios.get('https://api.example.com/data')
.then(res => console.log(res.data))
.catch(err => console.error(err));
Fetch vs. Axios
| Feature | Fetch | Axios |
|---|---|---|
| Size | Built‑in (0 KB extra) | ~13 KB minified |
| JSON Handling | Manual (res.json()) | Automatic |
| Error Handling | Network errors only | Network + HTTP status (e.g., 404) |
| Cancel Requests | Needs AbortController | Built‑in cancellation tokens |
| Best For | Quick prototypes | Production apps with auth, interceptors |
Use Axios when you need global auth headers, request/response interceptors, or more robust error handling.
Common Loading / Error Pattern
import { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => {
if (!res.ok) throw new Error('Fetch failed!');
return res.json();
})
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, []);
if (loading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<>
{data?.map(post => (
<div key={post.id}>- {post.title}</div>
))}
</>
);
}
Managing Loading UI
- Show a spinner or skeleton while
loadingistrue. - Display a friendly error message when
erroris set.
useEffect Patterns for Data Fetching
| Scenario | Dependency Array | Description |
|---|---|---|
| Fetch on mount | [] | Runs once after the first render. |
| Refetch on change | [userId] | Runs again whenever userId changes. |
| Cleanup on unmount | return function | Abort pending requests or unsubscribe. |
Abort Example with AbortController
useEffect(() => {
const controller = new AbortController();
fetch('https://api.example.com/data', { signal: controller.signal })
.then(res => res.json())
.then(setData)
.catch(err => {
if (err.name !== 'AbortError') setError(err);
});
return () => controller.abort();
}, []);
Pitfall: Omitting the dependency array causes the effect to run on every render, leading to infinite fetch loops.
Real‑World Scenarios
Weather App (Axios)
useEffect(() => {
axios.get('https://api.openweathermap.org/data/2.5/weather', {
params: { q: 'Bengaluru', appid: process.env.REACT_APP_OWM_KEY }
})
.then(res => setWeather(res.data))
.catch(setError);
}, []);
Infinite Scroll Feed
- Fetch additional pages when the user scrolls near the bottom.
- Append new items to existing state instead of replacing.
- Guard against duplicate entries by tracking the current page number.
Common Issues & Fixes
| Issue | Cause | Fix |
|---|---|---|
| Duplicate data | Missing page tracking | Store and increment a page counter. |
| Infinite loop | No dependency array in useEffect | Add appropriate dependencies ([] or [var]). |
| Memory leak | No cleanup on unmount | Abort fetches or unsubscribe in the cleanup function. |
| Stale closures | Dependencies omitted | Include all external variables in the dependency array or use functional state updates. |
| Race conditions | Overlapping requests | Cancel previous request with AbortController or Axios cancel token. |
| Double fetch in dev | React StrictMode runs effects twice | Accept that it only occurs in development; ensure cleanup works. |
Performance Tips
- Debounce rapid input changes before triggering a fetch.
- Use IntersectionObserver for lazy loading in infinite scroll.
- Cache results with libraries like React Query or SWR to avoid unnecessary network calls.
- Batch multiple requests when possible.
- Serve assets via CDN and enable compression (gzip/Brotli).
Security Reminder
Never commit API keys to source control. Store them in environment variables (process.env.REACT_APP_...) and reference them at runtime.
Advanced Topics (Brief Overview)
- Error Boundaries – Wrap components to catch rendering errors caused by failed fetches.
- React Suspense – Future‑proof loading states with “.
- Testing – Mock network calls using MSW or jest-fetch-mock.
- Caching Strategies – Stale‑while‑revalidate patterns for fast UI updates.
Further Learning
- Video tutorial: Data Fetching in React (search on YouTube for a comprehensive walkthrough).
You now have a solid foundation for fetching data in React—from basic fetch calls to robust patterns with Axios, loading states, cleanup, and performance considerations. Try building a GitHub user searcher or any API‑driven feature to solidify these concepts. Happy coding!