Stop Struggling With Data Fetching in React (React Day 7)

Published: (January 14, 2026 at 11:30 PM EST)
3 min read
Source: Dev.to

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

FeatureFetchAxios
SizeBuilt‑in (0 KB extra)~13 KB minified
JSON HandlingManual (res.json())Automatic
Error HandlingNetwork errors onlyNetwork + HTTP status (e.g., 404)
Cancel RequestsNeeds AbortControllerBuilt‑in cancellation tokens
Best ForQuick prototypesProduction 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 loading is true.
  • Display a friendly error message when error is set.

useEffect Patterns for Data Fetching

ScenarioDependency ArrayDescription
Fetch on mount[]Runs once after the first render.
Refetch on change[userId]Runs again whenever userId changes.
Cleanup on unmountreturn functionAbort 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

IssueCauseFix
Duplicate dataMissing page trackingStore and increment a page counter.
Infinite loopNo dependency array in useEffectAdd appropriate dependencies ([] or [var]).
Memory leakNo cleanup on unmountAbort fetches or unsubscribe in the cleanup function.
Stale closuresDependencies omittedInclude all external variables in the dependency array or use functional state updates.
Race conditionsOverlapping requestsCancel previous request with AbortController or Axios cancel token.
Double fetch in devReact StrictMode runs effects twiceAccept 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!

Back to Blog

Related posts

Read more »

React Coding Challenge : Card Flip Game

React Card Flip Game – Code tsx import './styles.css'; import React, { useState, useEffect } from 'react'; const values = 1, 2, 3, 4, 5; type Card = { id: numb...