Przejdź do głównej zawartości

2. Programowanie

W jaki sposób zrobić X w projekcie? Tutaj właśnie się tego dowiesz! Zachęcamy do pobieżnego przejrzenia całej strony, żeby kojarzyć co fajnego można tutaj znaleźć.

Pobieranie danych z API

Tutaj mamy dwie ścieżki:

  1. React Server Components

    React Server Components (RSC) to domyślne podejście w Next.js 14+. Dzięki nim dane są pobierane po stronie serwera, co eliminuje konieczność zarządzania stanami ładowania i zapewnia szybsze ładowanie stron. Zaletami jest automatyczne renderowanie danych na serwerze, brak konieczności zarządzania stanami ładowania i są proste w użyciu.

    app/products/page.tsx
    export default async function ProductsPage() {
    // Pobieranie danych z API po stronie serwera
    const data = await fetch("https://api.example.com/data");
    const products = await data.json();
    return (
    <div>
    <h1>Produkty</h1>
    <ul>
    {products.map((product) => (
    <li key={product.id}>
    {product.name} - {product.price} PLN
    </li>
    ))}
    </ul>
    </div>
    );
    }
  2. Tanstack Query

    Tego używamy gdy chcemy mieć większą kontrolę nad tym co się dzieje w naszej aplikacji, potrzebujemy odświeżać często dane albo na przykład mamy jakąś skomplikowaną logikę po stronie klienta (typu użytkownik najpierw wybiera jakąś zakładkę i dopiero wtedy pobieramy coś z api albo jakikolwiek case z bardziej zaawansowanym filtrowaniem)

    app/products/page.tsx
    "use client";
    import { useQuery } from "@tanstack/react-query";
    export default function ProductsList() {
    const {
    data: products,
    isLoading,
    error,
    refetch,
    } = useQuery({
    queryKey: ["products"],
    queryFn: async () => {
    const data = await fetch("https://api.example.com/data");
    const products = await data.json();
    return products;
    },
    });
    if (isLoading) return <p>Ładowanie danych...</p>;
    if (error) return <p>Wystąpił błąd podczas pobierania danych.</p>;
    return (
    <ul>
    {products.map((product) => (
    <li key={product.id}>
    {product.name} - {product.price} PLN
    </li>
    ))}
    </ul>
    );
    }

Do pobierania danych też potrzeba klienta API i tutaj mam zachęcam do korzystania z natywnego fetch , a za używanie axiosa bez powodu będę ucinał pensje, jest bardzo mało powodów do używania axiosa w 2024 roku.

Wysyłanie danych do API

Tutaj jestem opinionated i według mnie jedynym słusznym wyborem jest Tanstack Query i jego mutacje, nie próbujcie tego robić inaczej, bo będziecie sobie pluć w brodę

Zarządzanie stanem

Do globalnego stanu używamy Jotai, a do lokalnego useState/useReducer jak serio to jest coś skomplikowanego

Nigdy Context API, chyba, że macie BARDZO dobry powód

Nazwane i domyślne exporty

Umówiliśmy się co do jednej konwencji pisania stron i komponentów. Zawsze używamy nazwanych eksportów.

app/products/components/ProductList.tsx
// ✅
export function ProductList() {
return <div>Lista produktów</div>;
}
// ✅
export const formatDate = (date: Date) => {
return date.toLocaleDateString();
};
// ❌
export default function ProductList() {
return <div>Lista produktów</div>;
}
// ❌
const formatDate = (date: Date) => {
return date.toLocaleDateString();
};
export default formatDate;

Default eksportów używamy tylko na stronach typu page.tsx, bo NextJS tego wymaga:

app/products/page.tsx
// ✅
export default function ProductsPage() {
return <div>Produkty</div>;
}

Formularze

Zapraszam do dokumentacji shadcn’a, tam większość jest dobrze opisana:

https://ui.shadcn.com/docs/components/form

Autentykacja

Nie mieliśmy jeszcze za dużo projektów, które by wymagały autentykacji, ale tutaj raczej zalecam iść w klasykę i klepnąć to w AuthJS. Jest to rozwijany od lat produkt, który można w łatwy sposób zintegrować z projektem w NextJS. Zawiera duży funkcji, takich jak logowanie OAuth2 czy magicznymi linkami, sesje bazujące na bazie danych lub tokenach JWT czy automatyczną ochronę przed CSRF. Ma dobrze rozwiniętą społeczność i dokumentację oraz masę tutoriali na YouTubie.

Dodatkowo w ramach ciekawostki podrzucam Wam projekt działający pod nazwą BetterAuth. Jest to stosunkowo nowy projekt, który w wersję stabilną wszedł w listopadzie 2024 roku, aczkolwiek jest dobrze przemyślany i aktywnie rozwijany. Zalety tego projektu to między innymi, jeszcze łatwiejsza instalacja niż AuthJS czy rozwiązanie pluginowe, np. jeśli potrzebujecie użyć Passkeys to dodajecie taki plugin do configu. Do tego bardzo prosta dokumentacja. Polecam się zabawić.

Jeśli robicie to DIY, to pewnie będziecie musieli sobie odpowiedzieć na pytanie gdzie trzymać tokeny i tutaj są dwie opcje:

  • LocalStorage - protsza opcja, ale mniej bezpieczna i bardziej podatna na ataki XSS
  • Cookies HttpOnly - bardziej bezpieczna opcja, ale trudniejsza w implementacji, źle zaimplementowane może prowadzić do ataków CSRF

Na potrzeby Solvro cokolwiek wybierzecie będzie dobrze, a jeśli kogoś temat bardziej interesuje to tutaj można sobie poczytać:

WYSIWYG

Strasznie nie lubię tego tematu, bo tu jest milion wyborów i milion + 1 złych, obecnie rekomenduje:

https://shadcn-minimal-tiptap.vercel.app/

Tabelki

Do tworzenia bardziej zaawansowanych tabelek polecam https://tanstack.com/table/latest. Jest dość skomplikowany i ma wysoki próg wejścia, ale pozwoli wam na wszystko co sobie wymyślicie.

Jako przykład polecam DataTable z shadcn’a: https://ui.shadcn.com/docs/components/data-table

Jeśli tabelka ma więcej niż 1000 wierszy to jest moment, żeby przenieść logikę filtrowania, paginacji i sortowania na backend, frontend przy takich ilościach powoli może zacząć zamulać. Przy 10k+ ilości wierszy to jest must-have.

a11y

Za wsadzanie linka w przycisk będę karał tygodniową chłostą, to nie jest poprawny html, sam react krzyczy, że nie można tak robić i czytniki ekranów się zepsują jak spróbują to przeczytać

Więcej na ten temat znajdziesz w poradniku o dostępności