Build a dynamic React news feed by storing articles as data, rendering each article with a stable ID key, and deriving filtered or sorted views from the original records. For remote feeds, choose a framework loader or client-side cache when your app supports one; a manual useEffect fetch needs deliberate loading, error, empty, and success states plus request cleanup.
1. Model each news item as data
Keep article records separate from their presentation. The fields below are a practical example, not a schema React requires. Replace them with the properties your API actually returns.
As an Amazon Associate I earn from qualifying purchases.
const articles = [
{
id: "story-101",
headline: "Example headline",
summary: "A short description of the story.",
source: "Example News",
publishedAt: "2026-10-04T09:30:00Z",
imageUrl: "/images/example.jpg",
},
];
Use a stable, unique identifier from the data source for each item. Avoid generating keys during rendering or using the array index when entries may be inserted, removed, or reordered: React relies on keys to match list items across updates. Its Rendering Lists guide explains that keys identify which array item each component corresponds to.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
2. Render the feed from the array
Make an article card responsible for presenting one record, then use map() to create the repeated cards. This keeps the feed data-driven and makes the item layout reusable.
#1 Best Overall
function ArticleCard({ article }) {
return (
<article>
{article.imageUrl && (
<img src={article.imageUrl} alt="" />
)}
<p>{article.source}</p>
<h2>{article.headline}</h2>
<p>{article.summary}</p>
<time dateTime={article.publishedAt}>
{new Date(article.publishedAt).toLocaleString()}
</time>
</article>
);
}
function NewsFeed({ articles }) {
return (
<section aria-label="Latest news">
{articles.map((article) => (
<ArticleCard key={article.id} article={article} />
))}
</section>
);
}
The empty image alt is appropriate only when the image is decorative and adds no information beyond the headline. If the image conveys distinct content, supply useful alternative text from your data.
3. Filter or sort without mutating source data
For search or category controls, derive the displayed list from the records rather than changing the original array. React documents filter() and map() as standard ways to select and transform data for list rendering.
function getVisibleArticles(articles, query) {
const normalizedQuery = query.trim().toLowerCase();
return articles
.filter((article) =>
article.headline.toLowerCase().includes(normalizedQuery)
)
.toSorted((a, b) =>
new Date(b.publishedAt) - new Date(a.publishedAt)
);
}
toSorted() returns a sorted copy; if your supported JavaScript environments do not include it, use [...filtered].sort(...) instead. Keep the sort direction and filtering rules aligned with your product—for example, a feed may sort by publication time, editorial priority, or a server-provided ranking.
Recommended Free Tools
4. Choose how remote data enters the feed
Fetching is an architectural choice, not a requirement of the list component. React says framework data-loading mechanisms are generally more efficient than writing Effects manually. Router loaders or server fetching can support prefetching and help avoid network waterfalls; a client-side cache can help with caching and request coordination. The right fit depends on the app rather than one universal React rule.
Rank #3
| Approach | Useful when | Trade-off to consider |
|---|---|---|
| Framework or router data loading | Your app already uses a framework or router with a data API. | Use the framework’s conventions; available behavior depends on that framework and its configuration. |
| Client-side cache | Multiple views need the same feed or you need caching and request coordination. | Add and configure a data layer rather than treating every component render as an isolated request. |
| Manual fetch in an Effect | A small client-only example or app needs a direct component-level request. | You must handle loading, errors, cleanup, caching needs, and possible request waterfalls yourself. |
React’s useEffect documentation notes that fetching directly in Effects is manual: it does not itself provide preloading or caching, can create network waterfalls, and requires handling race conditions. If your framework offers server rendering or route-level data loading, consider whether it should supply the initial feed instead of waiting for the component to render and then fetch.
5. For a manual fetch, model states and clean up requests
The component below is an illustrative client-side pattern. Its URL and expected JSON shape are examples; adapt them to your service’s API contract.
Rank #4
import { useEffect, useState } from "react";
function useNewsFeed(url) {
const [state, setState] = useState({
status: "loading",
articles: [],
error: null,
});
useEffect(() => {
const controller = new AbortController();
async function load() {
setState({ status: "loading", articles: [], error: null });
try {
const response = await fetch(url, {
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
const articles = await response.json();
setState({ status: "success", articles, error: null });
} catch (error) {
if (error.name !== "AbortError") {
setState({ status: "error", articles: [], error });
}
}
}
load();
return () => controller.abort();
}, [url]);
return state;
}
function RemoteNewsFeed({ url }) {
const { status, articles, error } = useNewsFeed(url);
if (status === "loading") return <p>Loading news…</p>;
if (status === "error") {
return <p role="alert">Could not load the news feed. {error.message}</p>;
}
if (articles.length === 0) return <p>No stories are available.</p>;
return <NewsFeed articles={articles} />;
}
Why the dependency and cleanup matter
The Effect depends on url, so a changed feed URL starts a request for the new feed. Cleanup aborts the prior request; without cancellation or another way to ignore stale results, a slower response for an earlier query could overwrite newer feed data. React’s useEffect guidance recommends aborting a fetch or ignoring its result during cleanup.
Make each visible state intentional
- Loading: indicate that the requested feed is not ready yet.
- Error: give the user a readable failure message and consider a retry control if the product supports retries.
- Empty: distinguish a successful response with no stories from a failed request.
- Success: render the records, with any product-specific fallback for missing optional fields.
These states are product decisions; React’s app-building guidance treats loading, error, and caching as concerns to plan for rather than incidental details. See You Might Not Need an Effect for guidance on when effects are appropriate and how framework data loading can fit into an app.
Best Value
6. Refreshing, pagination, and feed-specific behavior
A changing news feed may need refresh controls, pagination, or live updates, but those behaviors depend on the API and product requirements. This example refetches when its URL changes; it does not define a polling interval, cursor format, pagination strategy, or real-time transport. Implement those against the service’s documented contract, and retain the same principles: identify records stably, represent request states explicitly, and prevent older responses from replacing newer results.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




