Jak powstał Destinations (cz. 4): chronione trasy w React Router
14.10.2026 · 2 min czytania
W części 3 dodałem
logowanie i wiem już, kto jest zalogowany (dzięki AuthContext). Zostało
pytanie: jak fizycznie nie wpuścić niezalogowanych do panelu szkoleniowca?
Ukrycie linku to nie zabezpieczenie#
Pierwsza myśl: „schowam przycisk do panelu, jak ktoś nie jest zalogowany”. Tylko że to żadna ochrona.
Potrzebowałem czegoś, co naprawdę pilnuje trasy — sprawdza, czy jesteś zalogowany, zanim w ogóle pokaże panel. A jeśli nie jesteś, odsyła Cię do logowania.
ProtectedRoute — strażnik trasy#
W React Router zrobiłem komponent ProtectedRoute, który opakowuje chronione
trasy. Układ tras wygląda tak:
<Route
path="/panel"
element={
<ProtectedRoute>
<Panel />
</ProtectedRoute>
}
/>
Generator i logowanie są publiczne, a /admin siedzi wewnątrz
ProtectedRoute — czyli przechodzi przez strażnika. Sam strażnik:
import { Navigate } from "react-router-dom";
import { useAuth } from "../contexts/useAuth";
import type { ReactNode } from "react";
const ProtectedRoute = ({ children }: { children: ReactNode }) => {
const { currentUser } = useAuth();
if (!currentUser) {
return <Navigate to="/login" replace />;
}
return children;
};
export default ProtectedRoute;
Pułapka, w którą można wpaść: stan ładowania#
Lekarstwo to dołożenie stanu loading w AuthContext (ustawianego w
onAuthStateChanged) i wstrzymanie decyzji, dopóki Firebase nie skończy:
const ProtectedRoute = ({ children }: { children: ReactNode }) => {
const { currentUser, loading } = useAuth();
if (loading) {
return null; // albo <Spinner />
}
if (!currentUser) {
return <Navigate to="/login" replace />;
}
return children;
};
Dopóki loading jest true, nic nie renderujemy (albo pokazujemy spinner) —
więc nie ma jak omyłkowo przekierować. To zostawiam sobie na kolejny krok.
Najważniejsze: to wciąż tylko połowa#
I tu wracam do lekcji z części 3. ProtectedRoute jest ważny, ale nie jest
prawdziwym zabezpieczeniem danych.
Dopiero obie warstwy razem dają sensowne bezpieczeństwo: jedna dba o to, co widać, druga o to, co można zrobić z danymi.
W części 5 — finał serii:
dlaczego cała aplikacja powstała, czyli generowanie testów i tabel do
druku (i CSS, o którym mało kto myśli: @media print).