Przejdź do głównej zawartości

04. Serwis newsowy

Zbudujesz serwis newsowy agregujący artykuły z różnych kategorii — technologia, sport, nauka, biznes. Użytkownik może przeglądać artykuły, filtrować po kategorii i wyszukiwać po słowie kluczowym.

Czego się nauczycie?

  • Integracja z zewnętrznym News API
  • Obsługa asynchroniczności (fetch + async/await)
  • Zarządzanie stanem filtrowania i paginacji
  • Obsługa błędów API i limitów żądań
  • Praca zespołowa — jeden robi widok listy i filtry, drugi wyszukiwarkę i paginację

W prawdziwej firmie...

Integracja z zewnętrznymi API, obsługa limitów, kluczy API i błędów sieciowych to codzienność każdego Front-End developera. News API to doskonały przykład prawdziwego, limitowanego API.

Umiejętności rynkowe

  • Asynchroniczne pobieranie danych
  • Obsługa kluczy API (env variables)
  • Paginacja / lazy loading
  • Debouncing wyszukiwarki
  1. Lista artykułów — tytuł, miniatura, źródło, data i krótki opis

  2. Filtry kategorii — technologia, sport, nauka, biznes, rozrywka

  3. Wyszukiwarka — wyszukiwanie artykułów po słowie kluczowym

  4. Widok artykułu — pełny artykuł lub link do zewnętrznej strony

  5. Zakładki / Saved — zapisywanie artykułów do przeczytania później

Strona główna

Hero z najnowszym artykułem + lista kart artykułów. Nawigacja kategorii i wyszukiwarka.

Widok kategorii

Artykuły przefiltrowane po kategorii. URL: /category/technology.

Zapisane artykuły

Lista artykułów dodanych przez użytkownika (localStorage). URL: /saved.

{
"source": { "id": "techcrunch", "name": "TechCrunch" },
"title": "React 19 is now stable",
"description": "The React team has released React 19 with new features...",
"url": "https://techcrunch.com/...",
"urlToImage": "https://tc.com/img/react19.jpg",
"publishedAt": "2025-03-01T12:00:00Z",
"content": "Full article text here..."
}

Minimalne wymagania:

  • Lista artykułów z lokalnych danych (minimum 15 artykułów w mockData.js)
  • Filtry kategorii (przyciski)
  • Kliknięcie artykułu otwiera zewnętrzny link
  • Wyszukiwarka po tytule
  • Responsywne karty artykułów
  • Routing: /, /category/:name, /saved
  • Foldersrc/
    • Folderdata/
      • articles.js
    • Foldercomponents/
      • ArticleCard.jsx
      • CategoryNav.jsx
      • SearchBar.jsx
    • Folderpages/
      • HomePage.jsx
      • CategoryPage.jsx
      • SavedPage.jsx
Ocena: 3.0
src/hooks/useDebounce.js
import { useState, useEffect } from 'react';
function useDebounce(value, delay = 300) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debouncedValue;
}
export default useDebounce;
// Użycie w komponencie:
// const debouncedSearch = useDebounce(searchQuery, 400);
// useEffect(() => { fetchNews(debouncedSearch); }, [debouncedSearch]);
src/hooks/useNews.js
import { useState, useEffect } from 'react';
const API_KEY = import.meta.env.VITE_NEWS_API_KEY;
function useNews(category = 'general', query = '') {
const [articles, setArticles] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const url = query
? `https://gnews.io/api/v4/search?q=${query}&token=${API_KEY}`
: `https://gnews.io/api/v4/top-headlines?category=${category}&token=${API_KEY}`;
setLoading(true);
fetch(url)
.then((res) => res.json())
.then((data) => setArticles(data.articles || []))
.catch((err) => setError(err.message))
.finally(() => setLoading(false));
}, [category, query]);
return { articles, loading, error };
}

Powodzenia!

Serwis newsowy to projekt, który wygląda profesjonalnie i pokazuje umiejętność pracy z prawdziwym API. Pamiętajcie o obsłudze limitów — w wariancie A używajcie lokalnych danych, żeby nie wyczerpać darmowego limitu podczas developmentu!