Moduł 5 - Zajęcia 10 - Nawigacja
Nawigacja po programie
React Router pozwala wykonać nawigację nie tylko po kliknięciu w Link, ale również po określonym działaniu użytkownika, zdarzeniu lub efekcie, na przykład po kliknięciu na przycisk, po wysłaniu formularza, po wyniku zapytania HTTP i tym podobne. Dla przykładu wykorzystujemy proces logowania użytkownika w aplikacji. Po wysłaniu formularza na stronie logowania wykonujemy nawigację na stronie profilu użytkownika, ale tylko jeśli zapytanie HTTP zakończyło się sukcesem.
Pierwszy sposób to hook useNavigate. Dostarcza nam funkcję navigate, do której przy wywołaniu przekazujemy ścieżkę określającą dokąd należy wykonać nawigację. Jest to imperatywny sposób, ale bardziej elastyczny i wymaga mniejszej ilości kodu.
src/pages/Login.jsx
import { useNavigate } from "react-router-dom";
export const Login = () => {
const navigate = useNavigate();
const handleSubmit = async values => {
const response = await FakeAPI.login(values);
if (response.success) {
navigate("/profile", { replace: true });
}
};
return (
<div>
<h1>Login page</h1>
<LoginForm onSubmit={handleSubmit} />
</div>
);
};
Zwróć uwagę na drugi, nieobowiązkowy argument funkcji navigate - to obiekt parametrów. Właściwość replace, domyślnie false, kontroluje, w jaki sposób zostanie dodany nowy zapis do stosu historii. Wróćmy do analogii ze stertą dokumentów. Domyślnie nowa kartka zostanie dodana na górze sterty, co w żaden sposób nie wpłynie na pozostałe karty. Jeżeli wskazać wartość true, to nowa karta podmieni tę, która jest na samym wierzchu. Wykorzystuje się to dość rzadko, na przykład przy logowaniu, aby użytkownik nie mógł powrócić przyciskiem "wróć" na stronę logowania po wejściu, ponieważ jest już w systemie i nie ma tam nic więcej do zrobienia.
Drugi sposób to komponent Navigate - owinięcie hooka useNavigate. Wykonuje nawigację w momencie renderowania. Ścieżka dla nawigacji i nieobowiązkowe parametry przekazywane są oddzielnymi propsami. Taki sposób jest bardziej deklaratywny, ale mniej elastyczny i wymaga więcej kodu.
src/pages/Login.jsx
import { Navigate, useState } from "react-router-dom";
export const Login = () => {
const [isLoginSuccess, setIsLoginSuccess] = useState(false);
const handleSubmit = async values => {
const response = await FakeAPI.login(values);
setIsLoginSuccess(response.success);
};
if (isLoginSuccess) {
return <Navigate to="/profile" replace />;
}
return (
<div>
<h1>Login page</h1>
<LoginForm onSubmit={handleSubmit} />
</div>
);
};
Trzecim sposobem jest wykorzystanie funkcji redirect. Jest ona istotnie rzadziej stosowana, ale w konkretnych przypadkach jest najlepszym wyborem.
import { redirect } from "react-router-dom";
const loader = async () => {
const user = await getUser();
if (!user) {
return redirect("/login");
}
return null;
};
CO JEST LEPSZE? To, jaki sposób wykorzystać, zależy tylko od twoich preferencji i wymagań zadania. W jednym przypadku będzie ci wygodnie wykorzystać deklaratywny Navigate, w drugim - imperatywny useNavigate. Funkcji redirect używamy za to, gdy chcemy zrobić przekierowanie bez interakcji użytkownika. Dobrym przykładem jest sprawdzenie czy użytkownik jest zalogowany - jeśli nie jest to używamy funkcji redirect i przenosimy go na stronę logowania