React Router: navigacija SPA aplikacijose

Kodėl navigacija SPA yra kitokia nei įprastose svetainėse

Prisimenu, kaip prieš keletą metų pirmą kartą susidūriau su Single Page Application koncepcija. Įpratęs prie tradicinių svetainių, kur kiekvienas paspaudimas ant nuorodos reiškė naują užklausą į serverį ir viso puslapio perkrovimą, staiga atsidūriau pasaulyje, kur viskas vyksta naršyklėje. Jokių baltų ekranų, jokio to nemalonaus mirksėjimo – tiesiog sklandus turinys keičiasi prieš akis.

Bet štai problema: jei viskas vyksta vienoje puslapio versijoje, kaip tada veikia URL? Kaip grįžti atgal? Kaip pasidalinti konkrečiu puslapiu su kolega? Čia ir prasideda React Router istorija. Ši biblioteka sprendžia fundamentalią problemą – ji suteikia SPA aplikacijoms normalią navigaciją, kokią vartotojai tikisi matyti bet kurioje svetainėje.

Tradicinėse svetainėse serveris gauna užklausą, apdoroja URL, nusprendžia ką grąžinti ir siunčia visą HTML dokumentą. React aplikacijoje viskas jau yra naršyklėje – JavaScript kodas, komponentai, logika. React Router veikia kaip eismo reguliuotojas, kuris stebi URL pasikeitimus ir nusprendžia, kuriuos komponentus parodyti, nesikreipdamas į serverį.

Kaip pradėti dirbti su React Router

Pirmiausia reikia įsidiegti biblioteką. Šiandien dauguma projektų naudoja šeštą versiją, nors kai kurie dar tebesilaiko penktos. Diegimas paprastas:

„`
npm install react-router-dom
„`

Pagrindinė koncepcija yra tokia: jūs apgaubiate savo aplikaciją `BrowserRouter` komponentu, tada apibrėžiate maršrutus naudodami `Routes` ir `Route` komponentus. Skamba abstrakčiai, bet praktikoje atrodo taip:

„`jsx
import { BrowserRouter, Routes, Route } from ‘react-router-dom’;

function App() {
return (


} />
} />
} />


);
}
„`

`BrowserRouter` naudoja HTML5 History API, kad valdytų URL be hash simbolių. Tai reiškia, kad jūsų adresai atrodys normaliai: `/products` vietoj `/#/products`. Yra ir `HashRouter` variantas, bet jį naudoju tik tada, kai tikrai neturiu kitos išeities – pavyzdžiui, kai hostingas neleidžia konfigūruoti serverio nukreipimų.

Svarbu suprasti, kad `BrowserRouter` turi būti vienas visai aplikacijai. Dažnai matau pradedančiuosius, kurie bando dėti kelis routerius skirtinguose komponentuose – tai sukelia problemų. Vienas routeris viršuje, ir viskas veikia sklandžiai.

Link komponentas ir navigacijos mechanika

Kai turite apibrėžtus maršrutus, reikia būdo tarp jų judėti. Galite naudoti įprastą `` tagą, bet tai sukels viso puslapio perkrovimą – būtent to, ko norime išvengti. Todėl React Router suteikia `Link` komponentą:

„`jsx
import { Link } from ‘react-router-dom’;

function Navigation() {
return (

);
}
„`

`Link` renderina `` tagą, bet perima click įvykį ir naudoja History API vietoj standartinio naršyklės elgesio. Rezultatas – greita navigacija be perkrovimų.

Yra ir `NavLink` komponentas, kuris ypač naudingas navigacijos meniu. Jis automatiškai prideda `active` klasę, kai esate atitinkamame puslapyje:

„`jsx
isActive ? ‘active-link’ : ‘link’}
>
Produktai

„`

Tai labai patogu, kai norite vizualiai paryškinti, kuriame puslapyje vartotojas šiuo metu yra. Anksčiau tam reikėjo rašyti papildomą logiką, dabar viskas veikia iš dėžės.

Dinaminiai maršrutai ir parametrai

Tikrasis React Router galios atsiskleidimas prasideda, kai pradedate dirbti su dinaminiais maršrutais. Retai kada turite fiksuotą puslapių sąrašą – dažniausiai turite produktų katalogą, vartotojų profilius, straipsnių archyvą. Kiekvienam elementui negalite sukurti atskiro maršruto.

Dinaminiai parametrai sprendžia šią problemą:

„`jsx
} />
} />
} />
„`

Dvitaškis nurodo, kad tai kintamoji maršruto dalis. Komponente galite pasiekti šiuos parametrus naudodami `useParams` hook’ą:

„`jsx
import { useParams } from ‘react-router-dom’;

function ProductDetail() {
const { id } = useParams();

// Dabar galite naudoti id, kad gautumėte produkto duomenis
const product = fetchProduct(id);

return

{product.name}

;
}
„`

Tai neįtikėtinai galinga funkcija. Galite kurti sudėtingus URL struktūras, kurios atspindi jūsų duomenų hierarchiją. Pavyzdžiui, e-komercijos svetainėje galite turėti `/categories/:categoryId/products/:productId`, ir abu parametrus lengvai pasieksite komponente.

Viena smulkmena, kurią svarbu žinoti – parametrai visada yra string tipo. Jei tikitės skaičiaus, nepamirškite konvertuoti: `const id = parseInt(params.id)`. Kartą praleidau šitą detalę ir valandą ieškojau, kodėl mano griežta lygybes patikra niekada neveikia.

Įdėtiniai maršrutai ir layout’ai

Kai aplikacija auga, greitai pastebite, kad daugelis puslapių turi bendrą struktūrą – headerį, šoninį meniu, footer’į. Įdėtiniai maršrutai (nested routes) leidžia tai elegantiškai organizuoti.

Pagalvokite apie admin panelę. Turite bendrą layout’ą su navigacija, o turinys keičiasi priklausomai nuo pasirinkto skyriaus:

„`jsx

}>
} />
} />
} />


„`

`AdminLayout` komponente naudojate `Outlet` komponentą, kad nurodytumėte, kur turėtų atsirasti įdėtinio maršruto turinys:

„`jsx
import { Outlet } from ‘react-router-dom’;

function AdminLayout() {
return (




);
}
„`

Kai vartotojas nueina į `/admin/dashboard`, React Router renderina `AdminLayout` su `Dashboard` komponente vietoje `Outlet`. Pereina į `/admin/users` – tas pats layout, bet turinys pasikeičia į `UsersList`.

Tai ne tik švaresnis kodas – tai ir našumo optimizacija. Layout komponentas nepersirenduoja, kai keičiatės tarp įdėtinių maršrutų. Tik turinys atsinaujina. Jei layout’e turite kokią nors brangią logiką ar būseną, ji išlieka.

Programinė navigacija ir useNavigate

Ne visada navigacija vyksta per nuorodų paspaudimus. Kartais reikia nukreipti vartotoją po formos pateikimo, autentifikacijos ar kito įvykio. Tam naudojamas `useNavigate` hook’as:

„`jsx
import { useNavigate } from ‘react-router-dom’;

function LoginForm() {
const navigate = useNavigate();

const handleSubmit = async (credentials) => {
const success = await login(credentials);

if (success) {
navigate(‘/dashboard’);
}
};

return

;
}
„`

`navigate` funkcija priima kelią kaip argumentą. Galite perduoti ir skaičių – tai veikia kaip naršyklės istorijos žingsnis. `navigate(-1)` grąžina atgal, `navigate(-2)` du žingsnius atgal ir taip toliau.

Yra ir antrasis parametras su papildomomis opcijomis. Pavyzdžiui, `replace: true` pakeičia dabartinį istorijos įrašą vietoj naujo pridėjimo:

„`jsx
navigate(‘/login’, { replace: true });
„`

Tai naudinga, kai nenorite, kad vartotojas galėtų grįžti į tam tikrą puslapį. Pavyzdžiui, po sėkmingo prisijungimo nenorite, kad „atgal” mygtukas vestų į login formą.

Anksčiau tam buvo naudojamas `useHistory` hook’as, bet šeštoje versijoje jis pakeistas į `useNavigate`. Jei atnaujinate seną projektą, tai viena iš pagrindinių migracijos užduočių.

Apsauga maršrutų ir autentifikacija

Beveik kiekviena aplikacija turi puslapių, kurie prieinami tik prisijungusiems vartotojams. React Router pats savaime neturi įtaisytos autentifikacijos, bet suteikia visas priemones ją implementuoti.

Populiariausias būdas – sukurti wrapper komponentą, kuris patikrina autentifikaciją prieš renderindamas maršrutą:

„`jsx
function ProtectedRoute({ children }) {
const { isAuthenticated } = useAuth();
const location = useLocation();

if (!isAuthenticated) {
return ;
}

return children;
}

// Naudojimas



}
/>
„`

`Navigate` komponentas veikia kaip deklaratyvus nukreipimas. Kai jis renderinamas, vartotojas automatiškai nukreipiamas į nurodytą kelią. `state` prop’as leidžia perduoti informaciją apie tai, iš kur vartotojas atėjo – po prisijungimo galite jį grąžinti į pradinį puslapį.

Kai kurie kūrėjai naudoja loader funkcijas (nauja šeštoje versijoje), kad patikrintų autentifikaciją prieš komponentui renderinantis. Tai gali būti efektyviau, ypač kai reikia gauti duomenis iš serverio:

„`jsx
}
loader={async () => {
const user = await checkAuth();
if (!user) throw redirect(‘/login’);
return user;
}}
/>
„`

Kiekvienas projektas skirtingas, bet principas tas pats – patikrinti prieš renderinant, nukreipti jei reikia.

Kas toliau: modernios funkcijos ir geriausia praktika

React Router šeštoji versija pristatė nemažai naujovių, kurios keičia tai, kaip galvojame apie maršrutizavimą. Data loaders ir actions leidžia atskirti duomenų gavimą nuo komponentų logikos. ErrorBoundary integracija suteikia geresnį klaidų valdymą. Deferred data loading pagerina našumą dideliuose projektuose.

Bet pagrindiniai principai išlieka tie patys. Svarbiausia – suprasti, kaip URL atspindi aplikacijos būseną. Geras maršrutizavimas reiškia, kad vartotojas gali pasidalinti nuoroda, grįžti atgal, perkrauti puslapį – ir viskas veiks taip, kaip tikimasi.

Keli praktiniai patarimai iš asmeninės patirties: visada testuokite navigaciją su išjungtu JavaScript – taip suprasite, ar jūsų serverio konfigūracija teisinga. Naudokite `basename` prop’ą, jei aplikacija ne root kelyje. Nepamirškite 404 puslapio – paprastas `} />` gale maršrutų sąrašo.

Ir paskutinis dalykas – React Router nėra vienintelis pasirinkimas. Yra TanStack Router, Wouter, ir kiti. Bet React Router yra brandus, gerai dokumentuotas, ir turi didžiulę bendruomenę. Jei abejojate, pradėkite nuo jo. Vėliau visada galėsite pakeisti, jei projekto reikalavimai to pareikalaus.

Navigacija SPA aplikacijose nebėra sudėtinga problema, kurią reikia spręsti nuo nulio. React Router paverčia ją paprastu, deklaratyviu procesu. Apibrėžiate maršrutus, sujungiate komponentus, ir viskas tiesiog veikia. O tai, kad vartotojai net nepastebi, jog naudoja SPA – geriausias komplimentas jūsų darbui.

Daugiau

Logstash grok patterns: logų parserinimas

E-komercijos platformos: WooCommerce ar Shopify?