Best News API for React 2026 (RSC, SWR, TanStack Query)

Jacob Partington

Jacob Partington

·

24 mins ler

Best News API for React 2026 (RSC, SWR, TanStack Query)

Best News API for React Applications in 2026 (RSC, TanStack Query, SWR, and SSE)

Pick the wrong news API for your React app and you get the same failure modes every time: CORS errors in production, an API key shipped to main.js, a Next.js build that crashes because the vendor SDK imports fs, or a toy useEffect + fetch that re-fires on every render. The news-API question in 2026 is not really "which vendor?" — it's "which vendor plays well with the way React actually renders today."

Disclosure. APITube publishes this blog. APITube is one of the APIs listed below. Every React snippet runs as written.

TL;DR — the best news API for React in 2026

The best news API for React in 2026 is APITube, NewsData.io, or Perigon, because each one uses header-based auth (X-API-Key), returns clean JSON, and works identically in a Next.js 15 Server Component, a Route Handler, or a client-side useQuery. NewsAPI.org disqualifies itself for real React apps by blocking non-localhost browser origins and using ?apiKey= query-string auth.

APIBest React patternBrowser-safe?Auth
APITubeRSC or Route Handler proxyvia proxyX-API-Key header
NewsData.ioRSC or Route Handler proxyvia proxyheader
PerigonRSC or Route Handler proxyvia proxyheader
GNewsRoute Handler proxyvia proxy onlyquery param
TheNewsAPIRoute Handler proxyvia proxyheader
NewsAPI.orgRoute Handler proxyCORS-blocked from browsersquery param

The rest of this article is: why you must never put a news API key in a React component, three canonical React patterns (RSC, SWR, TanStack Query), useInfiniteQuery for paginated news, a live-news SSE hook, and production UX (Suspense + error boundary + skeleton).

This article is for you if

You are a React developer shipping to production — CRA, Vite SPA, Next.js App Router, or Remix. You want patterns that don't leak keys, don't re-render like a hamster wheel, and don't break the moment you try to paginate or stream.

Table of contents

Never put your API key in a React component

Most "News API in React" tutorials start like this:

// ❌ DON'T: key ships to browser, visible in DevTools → Network → main.js
function NewsFeed() {
  useEffect(() => {
    fetch(`https://api.example.com/news?apiKey=${process.env.NEXT_PUBLIC_NEWS_KEY}`)
      .then((r) => r.json()).then(setArticles);
  }, []);
}

Anything prefixed NEXT_PUBLIC_* (Next.js) or REACT_APP_* (Create React App) is inlined into the client bundle at build time. Open DevTools on any page using that component and the key is a few scroll-ticks away in a JS file. Most vendors will rotate or suspend a key the moment it shows up in a public GitHub search.

The fix is not a library — it's architecture. Put the key only in server-side code, then expose a thin proxy:

// ✅ DO: app/api/news/route.ts (Next.js 15 Route Handler)
export const runtime = "nodejs"; // or "edge"
export async function GET(req: Request) {
  const { searchParams } = new URL(req.url);
  const q = searchParams.get("q") ?? "news";
  const res = await fetch(
    `https://api.apitube.io/v1/news/everything?title=${encodeURIComponent(q)}&per_page=20`,
    { headers: { "X-API-Key": process.env.APITUBE_KEY! } } // server-only env var
  );
  const data = await res.json();
  return Response.json(data.results);
}

Client code now hits /api/news?q=openai — key stays on the server. Same pattern in Remix (loader/action), SvelteKit, Astro server routes, or a tiny Express/Hono proxy for a pure SPA.

NewsAPI.org is a special case: its CORS policy actively blocks non-localhost origins on the Developer plan, which means even if you wanted to call it from a React component it wouldn't work in production. A proxy is the only option. Every other major vendor is proxyable by default; NewsAPI.org requires it for browser code.

See our NewsAPI.org migration notes for the full story.

The 6 news APIs ranked for React

Same template per vendor: recommended pattern, minimal example, one quirk.

1. APITube

Recommended pattern: Next.js 15 RSC or Route Handler. Native fetch, X-API-Key header. Supports SSE streaming for live feeds.

// RSC
const res = await fetch(
  "https://api.apitube.io/v1/news/everything?title=openai&language.code=en",
  { headers: { "X-API-Key": process.env.APITUBE_KEY! }, next: { revalidate: 60 } }
);

Quirk: no official React SDK — that's a feature. Response includes sentiment, entities, summary. Works identically in Server Components, Route Handlers, and (via proxy) client hooks.

2. NewsData.io

Recommended pattern: Route Handler proxy + TanStack Query. Header auth supported.

const res = await fetch(
  "https://newsdata.io/api/1/latest?q=openai&language=en",
  { headers: { "X-API-Key": process.env.NEWSDATA_KEY! } }
);

Quirk: pagination uses a nextPage cursor string — ideal for useInfiniteQuery.

3. Perigon

Recommended pattern: RSC. Perigon's event-clustered response maps well onto server-rendered feature cards.

const res = await fetch(
  "https://api.goperigon.com/v1/all?q=openai&language=en",
  { headers: { "x-api-key": process.env.PERIGON_KEY! }, next: { revalidate: 120 } }
);

Quirk: richer schema (clusters, entities) — either render on the server or zod-parse to a slim client shape.

4. GNews

Recommended pattern: Route Handler proxy. Query-param auth means never touching this from a client component.

const res = await fetch(
  `https://gnews.io/api/v4/search?q=openai&lang=en&apikey=${process.env.GNEWS_KEY}`
);

Quirk: lower rate limits; cache aggressively with next: { revalidate: 300 }.

5. TheNewsAPI

Recommended pattern: Route Handler proxy. Header auth.

const res = await fetch(
  "https://api.thenewsapi.com/v1/news/all?search=openai&locale=us",
  { headers: { Authorization: `Bearer ${process.env.THENEWSAPI_KEY!}` } }
);

Quirk: tighter country coverage (~50 countries).

6. NewsAPI.org

Recommended pattern: Route Handler proxy, mandatory. Do NOT call from client.

const url = new URL("https://newsapi.org/v2/everything");
url.searchParams.set("q", "openai");
url.searchParams.set("apiKey", process.env.NEWSAPI_KEY!);
const res = await fetch(url);

Quirk: CORS-blocked on non-localhost; production requires the $449/mo Business tier. Default is not a good default for shipping React apps.

Pattern 1: Next.js 15 App Router + async RSC

Server Components let you await fetch() directly in a component. No useState, no useEffect, no client-side hydration of the news data. Key never touches the browser.

// app/news/page.tsx
export const revalidate = 60; // ISR: regenerate every 60s

async function fetchNews() {
  const res = await fetch(
    "https://api.apitube.io/v1/news/everything?title=technology&per_page=12",
    { headers: { "X-API-Key": process.env.APITUBE_KEY! }, next: { revalidate: 60 } }
  );
  if (!res.ok) throw new Error(`News fetch failed: ${res.status}`);
  const data = await res.json();
  return data.results as Article[];
}

export default async function NewsPage() {
  const articles = await fetchNews();
  return (
    <main className="grid gap-4 p-6">
      {articles.map((a) => (
        <article key={a.href}>
          <h2>{a.title}</h2>
          <p>{a.summary}</p>
          <a href={a.href}>Read →</a>
        </article>
      ))}
    </main>
  );
}

Next.js extends fetch() with cache controls documented at nextjs.org/docs/app/api-reference/functions/fetch. next: { revalidate: 60 } caches for 60 seconds; cache: 'no-store' disables caching for genuinely live data.

When the user clicks a filter, trigger a Server Action or navigate to /news?topic=x with useRouter — the RSC re-renders on the server with the new query, and only the HTML diff streams to the client.

Pattern 2: useSWR for a client-side feed

Use SWR when the feed is simple: latest headlines, no pagination, no complex cache invalidation. SWR is 5.3 KB gzipped and has sensible defaults — revalidate on focus, revalidate on reconnect, dedupe identical requests.

"use client";
import useSWR from "swr";

const fetcher = (url: string) => fetch(url).then((r) => r.json());

export function NewsList({ query }: { query: string }) {
  const { data, error, isLoading } = useSWR(
    `/api/news?q=${encodeURIComponent(query)}`,   // your Route Handler, not the vendor
    fetcher,
    { refreshInterval: 60_000 }                    // poll every minute
  );

  if (isLoading) return <NewsSkeleton />;
  if (error) return <NewsError onRetry={() => location.reload()} />;
  if (!data?.length) return <EmptyFeed />;

  return (
    <ul>
      {data.map((a: Article) => (
        <li key={a.href}><a href={a.href}>{a.title}</a></li>
      ))}
    </ul>
  );
}

Note: the hook hits /api/news, not the vendor. The key is on the server.

Pattern 3: TanStack Query + useInfiniteQuery for paginated news

TanStack Query is 16.2 KB gzipped and earns its weight when you need pagination, mutations, and shared cache state across the tree. useInfiniteQuery is the canonical pattern for infinite-scroll news feeds. Docs: tanstack.com/query.

"use client";
import { useInfiniteQuery } from "@tanstack/react-query";

type NewsPage = { articles: Article[]; nextCursor?: string };

async function fetchPage({ pageParam }: { pageParam?: string }): Promise<NewsPage> {
  const url = new URL("/api/news", location.origin);
  url.searchParams.set("q", "technology");
  if (pageParam) url.searchParams.set("cursor", pageParam);
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

export function InfiniteNews() {
  const {
    data, fetchNextPage, hasNextPage, isFetchingNextPage, status,
  } = useInfiniteQuery({
    queryKey: ["news", "technology"],
    queryFn: fetchPage,
    initialPageParam: undefined as string | undefined,
    getNextPageParam: (last) => last.nextCursor,
    staleTime: 30_000,
  });

  if (status === "pending") return <NewsSkeleton />;
  if (status === "error") return <NewsError />;

  return (
    <>
      {data.pages.flatMap((p) => p.articles).map((a) => (
        <article key={a.href}><h3>{a.title}</h3></article>
      ))}
      <button
        onClick={() => fetchNextPage()}
        disabled={!hasNextPage || isFetchingNextPage}
      >
        {isFetchingNextPage ? "Loading…" : hasNextPage ? "Load more" : "End of feed"}
      </button>
    </>
  );
}

Wire the button to an IntersectionObserver for true infinite scroll. The Route Handler returns { articles, nextCursor } — cursor comes from the vendor's pagination (NewsData's nextPage, APITube's next_page / has_next_pages, etc.).

Live news with SSE in a client component

When the product needs push updates, not polling, consume Server-Sent Events. APITube exposes text/event-stream. Wrap EventSource in a custom hook with reconnect:

"use client";
import { useEffect, useState } from "react";

export function useNewsStream(endpoint: string) {
  const [articles, setArticles] = useState<Article[]>([]);
  const [connected, setConnected] = useState(false);

  useEffect(() => {
    const es = new EventSource(endpoint); // hits YOUR proxy, not the vendor
    es.onopen = () => setConnected(true);
    es.onerror = () => setConnected(false); // EventSource auto-reconnects
    es.onmessage = (evt) => {
      const article = JSON.parse(evt.data) as Article;
      setArticles((prev) => [article, ...prev].slice(0, 50)); // cap memory
    };
    return () => es.close();
  }, [endpoint]);

  return { articles, connected };
}

// Usage
function LiveFeed() {
  const { articles, connected } = useNewsStream("/api/news/stream");
  return (
    <>
      <div>Status: {connected ? "🟢 live" : "🔴 reconnecting"}</div>
      <ul>{articles.map((a) => <li key={a.href}>{a.title}</li>)}</ul>
    </>
  );
}

The /api/news/stream Route Handler opens a long-lived fetch to APITube's SSE endpoint and pipes bytes straight through with ReadableStream. No extra library, no polling.

Production UX — Suspense, skeleton, error boundary

A three-div "Loading..." is not a UX. Compose Suspense + <ErrorBoundary> + skeleton:

import { Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function NewsSection() {
  return (
    <ErrorBoundary fallback={<NewsError />}>
      <Suspense fallback={<NewsSkeleton count={6} />}>
        <AsyncNewsList />
      </Suspense>
    </ErrorBoundary>
  );
}

function NewsSkeleton({ count = 6 }) {
  return (
    <ul className="grid gap-4">
      {Array.from({ length: count }).map((_, i) => (
        <li key={i} className="h-24 animate-pulse rounded bg-gray-200" />
      ))}
    </ul>
  );
}

Four states to handle — loading, error, empty, success. The empty state matters: a feed filter that returns zero articles should tell users why, not show a void.

useSWR vs TanStack Query for news feeds

Decision rule by scenario, tuned to news:

ScenarioPickWhy
Latest-headlines widget, single query, no paginationSWR5.3 KB, focus revalidation is ideal for "what's new?"
Search-as-you-type with debounce, 1-2 filtersSWRDedupe handles it; state is simple
Paginated / infinite-scroll news feedTanStack QueryuseInfiniteQuery is purpose-built
Saving articles (read-later), user mutations + cache syncTanStack QueryuseMutation + queryClient.invalidateQueries
Dashboard with 4+ news widgets sharing cached stateTanStack QueryGlobal cache, query keys, devtools

Numeric rule: if the news UI involves one hook per page, SWR is enough. If it involves three or more coordinated queries, or any mutation, go TanStack Query. The 11 KB difference pays for itself the first time you useInfiniteQuery.

What's changing for React in 2026-2027

Three shifts make the React-side news-API choice more consequential:

  1. RSC is now the default in Next.js and most new React frameworks. News APIs that rely on a browser-only SDK are increasingly awkward; vendors with plain REST + header auth work in the server tree without ceremony. Unlike a browser-first SDK, a clean REST API works identically in Server Components, Route Handlers, and Edge functions, which means you pick one vendor and ship everywhere.

  2. NEXT_PUBLIC_* public env vars are under tighter CI scrutiny. Security linters and deploy-time checks increasingly warn when public env vars are named like API keys. Teams shipping new codebases in 2026 will default to the proxy pattern; the old "just add NEXT_PUBLIC_" shortcut is becoming a CI failure.

  3. AI-native React apps retrieve news server-side. Apps built on Vercel AI SDK, LangChain.js, or Mastra with React UIs fetch news in the server tree before passing context to the model. Browser-side news fetching for AI flows is an anti-pattern. The React news-API pick in 2026 is effectively the Node news-API pick of a server framework that renders React.

Frequently asked questions

How do I fetch news in React?

The recommended way to fetch news in React in 2026 is to call a server-side proxy (Next.js Route Handler, Remix loader, or Express endpoint) that holds the API key, because calling a news API directly from a React component leaks the key into the client bundle. For production, pair the proxy with useSWR (simple feeds) or TanStack Query useQuery/useInfiniteQuery (paginated or complex feeds).

Is React Query better than SWR for news?

TanStack Query is better than SWR for news feeds that need pagination, mutations, or shared cache across components, because useInfiniteQuery and useMutation cover exactly those cases. SWR is better for a single latest-headlines hook because it is 5.3 KB versus TanStack Query's 16.2 KB. For a production news feed with infinite scroll, pick TanStack Query.

How do I build a news feed in Next.js?

To build a news feed in Next.js 15, create an async Server Component that await fetch()s the news API server-side with your key in a server-only env var, then render the results as HTML. Add next: { revalidate: 60 } for ISR. For infinite scroll, expose a Route Handler at /api/news and consume it from a client component with TanStack Query's useInfiniteQuery.

How do I hide my API key in React?

You hide your API key in React by keeping it in a server-only env var (no NEXT_PUBLIC_ or REACT_APP_ prefix) and calling the news API only from server code — a Next.js Route Handler, Remix loader, or a backend proxy. Anything prefixed NEXT_PUBLIC_* or REACT_APP_* gets inlined into the browser bundle and is visible in DevTools.

Can React call News API directly?

No, React cannot safely call NewsAPI.org directly in 2026, because its CORS policy blocks non-localhost browser origins on the Developer plan, and the ?apiKey= query-string auth would leak the key even if CORS allowed it. The correct pattern is a server-side proxy. Other vendors with header auth (APITube, NewsData.io, Perigon) are technically CORS-friendlier but should still be proxied in production for key security.

Verdict

The best news API for React in 2026 is the one that plays well with React's default rendering model — server-first, proxy the key, let a hook library handle cache on the client. APITube, NewsData.io, and Perigon all qualify; NewsAPI.org doesn't without a paid tier and a proxy. Whatever you pick, the proxy pattern is non-negotiable and the hook choice (useSWR vs useQuery) follows from the feed complexity, not from which library is trendy this quarter.

APITube ships a clean REST API that works equally well in Server Components, Route Handlers, and browser fetches behind a proxy — X-API-Key header, SSE streaming, 30 req / 30 min on the free tier, commercial use allowed. apitube.io

Related reading: Best News API in 2026: Complete Comparison Guide · Best News API for JavaScript & Node.js 2026 · Next.js fetch reference · TanStack Query docs

Resources

Related guides:

APITube - News API

Artigos relacionados

Next.js Multilingual App Tutorial 2026: UI + Content i18n
Developer Guides

Next.js Multilingual App Tutorial 2026: UI + Content i18n

Build a multilingual Next.js 16 app: next-intl for UI strings, APITube for content in 60+ languages, working hreflang and a multilingual sitemap. Server Components, RTL, and Vercel Edge deploy — free tier included.

React News Dashboard Tutorial 2026: SSE + TypeScript
Developer Guides

React News Dashboard Tutorial 2026: SSE + TypeScript

Build a real-time React news dashboard with TypeScript and Server-Sent Events. Full code, 429-safe fetch hook, sentiment filters, Vercel deploy.

Best News API for JavaScript & Node.js 2026 (+TS + SSE)
Insights

Best News API for JavaScript & Node.js 2026 (+TS + SSE)

Best news API for JavaScript and Node.js in 2026 — 7 picks compared, a reusable TypeScript fetch wrapper, SSE streaming, and production notes.

Best Free News APIs in 2026 (With Honest Limitations)
Insights

Best Free News APIs in 2026 (With Honest Limitations)

Best free news APIs in 2026 — honest limitations per API, production-safety flags, credits-vs-requests, dishonorable mentions. 5-question checklist.

Utilizamos cookies

Ao clicar em "aceitar", concorda com o armazenamento de cookies no seu dispositivo para fins funcionais e analíticos.