Obsługa danych i API Routes w Next.js

W poprzednim artykule omówiliśmy podstawy frameworka Next.js, jego możliwości, takie jak renderowanie po stronie serwera (SSR) i generowanie stron statycznych (SSG), a także podstawowy routing i nawigację. Dzisiaj skupimy się na jednym z kluczowych elementów, które pozwalają na budowanie pełnoprawnych aplikacji webowych: API Routes.

Next.js pozwala na tworzenie API w tym samym projekcie, co frontend, bez konieczności konfiguracji osobnego serwera. Dzięki temu możesz łatwo tworzyć funkcje backendowe, takie jak zapisywanie danych, przetwarzanie formularzy czy komunikacja z bazą danych, i integrować je bezpośrednio w swojej aplikacji.

W tym artykule pokażemy, jak tworzyć i obsługiwać własne API Routes w Next.js, jak przesyłać dane do API oraz jak pobierać dane z zewnętrznych API.

1. Tworzenie własnych API Routes w Next.js

Co to są API Routes?

API Routes w Next.js to specjalne pliki, które znajdują się w katalogu pages/api/. Każdy plik w tym katalogu odpowiada za określoną funkcjonalność backendową, taką jak obsługa zapytań HTTP (GET, POST, PUT, DELETE) i wykonanie odpowiednich operacji na danych. Możesz je traktować jak „mini-serwery”, które działają w ramach aplikacji Next.js.

Przykład prostego API Route

Aby stworzyć API Route, wystarczy stworzyć plik w folderze pages/api/. Na przykład, stwórzmy plik hello.js, który będzie odpowiadał na zapytania HTTP GET.

  1. W katalogu pages/api/ stwórz plik hello.js:
				
					// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Witaj w API Next.js!' });
}

				
			
  1. Teraz, po uruchomieniu aplikacji (np. npm run dev), możesz przejść do http://localhost:3000/api/hello w przeglądarce, aby zobaczyć odpowiedź:
				
					{"message":"Witaj w API Next.js!"}
				
			

W tym przykładzie stworzyliśmy prostą funkcję, która odpowiada na zapytanie GET. Funkcja handler przyjmuje dwa argumenty: req (żądanie) i res (odpowiedź). Używamy metody res.status(200).json(), aby zwrócić dane w formacie JSON.

Obsługa różnych metod HTTP

W Next.js API Routes możesz obsługiwać różne metody HTTP, takie jak GET, POST, PUT, DELETE. Przykład:

				
					// pages/api/contact.js
export default function handler(req, res) {
  if (req.method === 'GET') {
    // Obsługa zapytania GET
    res.status(200).json({ message: 'Dane kontaktowe' });
  } else if (req.method === 'POST') {
    // Obsługa zapytania POST
    const { name, email } = req.body;
    res.status(201).json({ message: `Dziękujemy za kontakt, ${name}!` });
  } else {
    // Obsługa innych metod
    res.status(405).json({ message: 'Metoda nieobsługiwana' });
  }
}

				
			

W tym przykładzie:

  • Jeśli użytkownik wyśle zapytanie GET, API zwróci dane kontaktowe.
  • Jeśli użytkownik wyśle zapytanie POST, API odbierze dane z formularza (np. imię i e-mail) i odpowie wiadomością powitalną.

2. Przesyłanie danych do API

Prześlijmy dane do API, używając metody POST w Next.js. Załóżmy, że mamy formularz, w którym użytkownicy wpisują swoje imię i e-mail. Gdy użytkownik wyśle formularz, dane zostaną przesłane do naszego API.

Tworzenie formularza

W pliku pages/index.js dodajemy prosty formularz:

				
					// pages/index.js
import { useState } from 'react';

const Home = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [message, setMessage] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    const response = await fetch('/api/contact', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ name, email }), // Przesyłamy dane w formacie JSON
    });

    const data = await response.json();
    setMessage(data.message); // Ustawiamy odpowiedź z serwera
  };

  return (
    <div>
      <h1>Formularz kontaktowy</h1>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="Twoje imię"
          value={name}
          onChange={(e) => setName(e.target.value)}
          required
        />
        <input
          type="email"
          placeholder="Twój e-mail"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />
        <button type="submit">Wyślij</button>
      </form>
      {message && <p>{message}</p>}
    </div>
  );
}

export default Home;

				
			

W tym kodzie:

  • Używamy hooków React (useState), aby przechowywać stan formularza.
  • Po kliknięciu przycisku „Wyślij” wywołujemy funkcję handleSubmit, która wysyła dane do API za pomocą metody POST. Dane są przesyłane jako JSON.

Obsługa danych na serwerze

W folderze pages/api/ stwórzmy plik contact.js, który będzie obsługiwał zapytanie POST:

				
					// pages/api/contact.js
export default function handler(req, res) {
  if (req.method === 'POST') {
    const { name, email } = req.body;

    // W tym miejscu moglibyśmy np. zapisać dane w bazie danych
    res.status(201).json({ message: `Dziękujemy za kontakt, ${name}!` });
  } else {
    res.status(405).json({ message: 'Metoda nieobsługiwana' });
  }
}

				
			

Gdy formularz zostanie wysłany, dane (imię i e-mail) trafią do naszego API, które zwróci odpowiedź z powiadomieniem powitalnym.

3. Pobieranie danych z zewnętrznych API

Next.js umożliwia również pobieranie danych z zewnętrznych API, co jest bardzo przydatne, gdy chcesz integrować swoją aplikację z serwisami zewnętrznymi (np. pobieranie danych pogodowych, wyników sportowych, produktów z e-commerce).

Przykład pobierania danych z API

Załóżmy, że chcemy pobrać dane o użytkownikach z fikcyjnego API (np. https://jsonplaceholder.typicode.com/users).

Stwórzmy plik pages/users.js, który będzie pobierał dane z tego API i wyświetlał listę użytkowników:

				
					// pages/users.js
import { useEffect, useState } from 'react';

const Users = () => {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      const data = await response.json();
      setUsers(data);
    };

    fetchData();
  }, []);

  return (
    <div>
      <h1>Lista użytkowników</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>{user.name} - {user.email}</li>
        ))}
      </ul>
    </div>
  );
}

export default Users;

				
			

W tym przykładzie:

  • Używamy hooka useEffect, aby pobrać dane z zewnętrznego API po załadowaniu komponentu.
  • Z danych (w formacie JSON) tworzymy listę użytkowników i wyświetlamy ich imiona oraz e-maile.

Obsługa błędów przy pobieraniu danych

Jeśli zapytanie do zewnętrznego API nie powiedzie się (np. brak połączenia z Internetem), warto obsłużyć błąd, aby aplikacja nie „wysypała się” i wyświetliła użytkownikowi odpowiednią informację.

				
					useEffect(() => {
  const fetchData = async () => {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      if (!response.ok) throw new Error('Nie udało się pobrać danych');
      const data = await response.json();
      setUsers(data);
    } catch (error) {
      console.error(error);
      setError('Wystąpił problem z pobraniem danych');
    }
  };

  fetchData();
}, []);

				
			

Teraz, jeśli coś pójdzie nie tak z połączeniem, użytkownik zobaczy komunikat o błędzie.

4. Obsługa zapytań POST, GET w API Routes

  • GET: Jest to najczęściej stosowana metoda, która służy do pobierania danych. W Next.js, zapytanie GET obsługujemy za pomocą metody res.status(200).json().

  • POST: Jest to metoda wykorzystywana do przesyłania danych na serwer. W Next.js dane można pobrać z ciała żądania za pomocą req.body. Przy odpowiedzi używamy metody res.status(201).json().

Podsumowanie

Tworzenie i obsługa API w Next.js za pomocą API Routes to świetna opcja, gdy potrzebujesz pełnej funkcjonalności aplikacji bez potrzeby tworzenia oddzielnego serwera. Dzięki Next.js możesz tworzyć backend w tym samym projekcie, co frontend, co znacząco ułatwia rozwój aplikacji. Możliwość obsługi zapytań GET i POST, przesyłania danych oraz integracji z zewnętrznymi API czyni Next.js bardzo wszechstronnym narzędziem do budowania aplikacji webowych.