Dacă tocmai ați început cu React, probabil că încă vă înfășurați capul în jurul întregului concept de aplicație cu o singură pagină.

Rutarea în mod tradițional funcționează astfel: să presupunem că introduceți text /contact în adresa URL. Browserul va face o cerere GET către server, iar serverul va returna o pagină HTML ca răspuns.

Dar, cu noua paradigmă a aplicației pentru o singură pagină, toate cererile URL sunt servite folosind codul client.

Aplicând acest lucru în contextul React, fiecare pagină va fi o componentă React. React-Router se potrivește cu adresa URL și încarcă componenta pentru pagina respectivă.

Totul se întâmplă atât de rapid și fără probleme, încât utilizatorul primește o experiență nativă asemănătoare aplicației în browser. Nu există o pagină goală strălucitoare între tranzițiile rutei.

În acest articol, veți afla cum să utilizați React-Router și componentele sale pentru a crea o aplicație cu o singură pagină. Deci, deschideți editorul de text preferat și să începem.

Configurați proiectul

Creați un nou proiect React executând următoarea comandă.

yarn create react-app react-router-demo

Voi folosi fire pentru a instala dependențele, dar puteți utiliza și npm.

Apoi, să instalăm react-router-dom.

yarn add react-router-dom

Pentru stilizarea componentelor, voi folosi cadrul Bulma CSS. Deci, să adăugăm și asta.

yarn add bulma

Apoi, importați bulma.min.css în index.js fișierul și curățați tot codul cazanului de pe App.js fişier.

import "bulma/css/bulma.min.css";

Acum că aveți proiectul configurat, să începem prin a crea câteva componente de pagină.

Crearea componentelor paginii

Creați un director de pagini în folderul src unde vom parca toate componentele paginii.

Pentru această demonstrație, creați trei pagini – Acasă, Despre și Profil.

Lipiți următoarele în interiorul componentelor Acasă și Despre.

// pages/Home.js

import React from "react";

const Home = () => (
  <div>
    <h1 className="title is-1">This is the Home Page</h1>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras gravida,
      risus at dapibus aliquet, elit quam scelerisque tortor, nec accumsan eros
      nulla interdum justo. Pellentesque dignissim, sapien et congue rutrum,
      lorem tortor dapibus turpis, sit amet vestibulum eros mi et odio.
    </p>
  </div>
);

export default Home;
// pages/About.js

import React from "react";

const About = () => (
  <div>
    <h1 className="title is-1">This is the About Page</h1>
    <p>
      Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
      inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus
      et ultrices posuere cubilia curae; Duis consequat nulla ac ex consequat,
      in efficitur arcu congue. Nam fermentum commodo egestas.
    </p>
  </div>
);

export default About;

Vom crea pagina de profil mai târziu în articol.

Creați componenta Navbar

Să începem prin a crea bara de navigare pentru aplicația noastră. Această componentă va utiliza fișierul <NavLink /> componentă din react-router-dom.

Creați un director numit „componente” în folderul src.

// components/Navbar.js

import React, { useState } from "react";
import { NavLink } from "react-router-dom";

const Navbar = () => {
  const [isOpen, setOpen] = useState(false);
  return ( 
  	<nav
      className="navbar is-primary"
      role="navigation"
      aria-label="main navigation"
    >
      <div className="container">
      	{/* ... */}
      </div>
    </nav>
  );
 };
 
 export default Navbar;

isOpen variabila de stare va fi utilizată pentru a declanșa meniul pe dispozitive mobile sau tablete.

Deci, să adăugăm meniul pentru hamburgeri.

const Navbar = () => {
  const [isOpen, setOpen] = useState(false);
  return ( 
  	<nav
      className="navbar is-primary"
      role="navigation"
      aria-label="main navigation"
    >
      <div className="container">
      <div className="navbar-brand">
          <a
            role="button"
            className={`navbar-burger burger ${isOpen && "is-active"}`}
            aria-label="menu"
            aria-expanded="false"
            onClick={() => setOpen(!isOpen)}
          >
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
          </a>
        </div>
      	{/* ... */}
      </div>
    </nav>
  );
 };

Pentru a adăuga linkul în meniu, utilizați <NavLink /> componentă de react-router-dom.

NavLink componentă oferă o modalitate declarativă de a naviga în jurul aplicației. Este similar cu Link componentă, cu excepția faptului că poate aplica un stil activ linkului dacă este activ.

Pentru a specifica la ce rută să navigați, utilizați to susțineți și treceți numele căii.
activeClassName prop va adăuga o clasă activă la link dacă este activă în prezent.

<NavLink
    className="navbar-item"
    activeClassName="is-active"
    to="/"
    exact
>
	Home
</NavLink>

În browser, fișierul NavLink componentă este redată ca un fișier <a> etichetați cu un href valoarea atributului care a fost transmisă în to recuzită.

De asemenea, aici trebuie să specificați exact prop, astfel încât să se potrivească exact cu adresa URL.

Adăugați toate linkurile și terminați Navbar componentă.

import React, { useState } from "react";
import { NavLink } from "react-router-dom";

const Navbar = () => {
  const [isOpen, setOpen] = useState(false);
  return (
    <nav
      className="navbar is-primary"
      role="navigation"
      aria-label="main navigation"
    >
      <div className="container">
        <div className="navbar-brand">
          <a
            role="button"
            className={`navbar-burger burger ${isOpen && "is-active"}`}
            aria-label="menu"
            aria-expanded="false"
            onClick={() => setOpen(!isOpen)}
          >
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
          </a>
        </div>

        <div className={`navbar-menu ${isOpen && "is-active"}`}>
          <div className="navbar-start">
            <NavLink className="navbar-item" activeClassName="is-active" to="/">
              Home
            </NavLink>

            <NavLink
              className="navbar-item"
              activeClassName="is-active"
              to="/about"
            >
              About
            </NavLink>

            <NavLink
              className="navbar-item"
              activeClassName="is-active"
              to="/profile"
            >
              Profile
            </NavLink>
          </div>

          <div className="navbar-end">
            <div className="navbar-item">
              <div className="buttons">
                <a className="button is-white">Log in</a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </nav>
  );
};

export default Navbar;

Dacă observați aici, am adăugat un buton de autentificare. Vom reveni la Navbar componentă din nou când discutăm traseele protejate mai târziu în ghid.

Redarea paginilor

Acum că Navbar componenta este configurată să adăugăm asta la pagină și să începem cu redarea paginilor.

Deoarece bara de navigare este o componentă obișnuită în toate paginile, în loc să apelați componenta din fiecare componentă a paginii, va fi o abordare mai bună pentru a reda Navbar într-un aspect comun.

// App.js

function App() {
  return (
    <>
      <Navbar />
      <div className="container mt-2" style={{ marginTop: 40 }}>
        {/* Render the page here */}
      </div>
    </>
  );
}

Acum, adăugați componentele paginii în interiorul containerului.

// App.js

function App() {
  return (
    <>
      <Navbar />
      <div className="container mt-2" style={{ marginTop: 40 }}>
        <Home />
      	<About />
      </div>
    </>
  );
}

Dacă verificați rezultatele acum, veți observa că atât pagina principală, cât și componenta despre pagina sunt redate pe pagină. Asta pentru că nu am adăugat încă nicio logică de rutare.

Trebuie să importați fișierul BrowserRouter component de la React Router pentru a adăuga capacitatea de a direcționa componentele. Tot ce trebuie să faceți este să înfășurați toate componentele paginii în interiorul fișierului BrowserRouter componentă. Aceasta va permite tuturor componentelor paginii să aibă logica de rutare. Perfect!

Dar, din nou, nimic nu se va schimba odată cu rezultatele – veți vedea în continuare ambele pagini redate. Trebuie să redați componenta paginii numai dacă adresa URL se potrivește cu o anumită cale. Acolo este Route componenta de la React Router intră în joc.

Router componenta are o path prop care acceptă calea paginii, iar componenta paginii ar trebui să fie înfășurată cu Router, așa cum se arată mai jos.

<Route path="/about">
  <About />
</Route>

Deci, să facem același lucru pentru Home componentă.

<Route exact path="/">
  <Home />
</Route>

exact prop mai sus spune Router componentă care să se potrivească exact cu calea. Dacă nu adăugați exact prop pe / calea, se va potrivi cu toate traseele începând cu a / inclusiv /about.

Dacă mergeți, verificați acum rezultatele, veți vedea în continuare ambele componente redate. Dar, dacă mergi la /about, veți observa că numai About componenta este redată. Veți vedea acest comportament, deoarece routerul continuă să potrivească adresa URL cu rutele chiar și după ce a egalat deja o rută.

Trebuie să spunem routerului să nu mai potrivească odată ce se potrivește cu o rută. Acest lucru se face folosind Switch componentă din React Router.

function App() {
  return (
    <BrowserRouter>
      <Navbar />
      <div className="container mt-2" style={{ marginTop: 40 }}>
        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
        </Switch>
      </div>
    </BrowserRouter>
  );
}

Gata! Ați configurat cu succes rutare în aplicația dvs. React.

Rute și redirecționare protejate

Când lucrați la aplicații din lumea reală, veți avea câteva rute în spatele unui sistem de autentificare. Veți avea trasee sau pagini care pot fi accesate doar de un utilizator conectat. În această secțiune, veți afla cum să implementați astfel de rute.

Vă rugăm să rețineți că nu voi crea niciun formular de autentificare sau niciun serviciu back-end să autentifice utilizatorul. Într-o aplicație reală, nu ați implementa autentificarea așa cum este demonstrat aici.

Să creăm componenta paginii de profil care ar trebui să fie accesată doar de utilizatorul autentificat.

// pages/Profile.js

import { useParams } from "react-router-dom";

const Profile = () => {
  const { name } = useParams();
  return (
    <div>
      <h1 className="title is-1">This is the Profile Page</h1>
      <article className="message is-dark" style={{ marginTop: 40 }}>
        <div className="message-header">
          <p>{name}</p>
        </div>
        <div className="message-body">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
          <strong>Pellentesque risus mi</strong>, tempus quis placerat ut, porta
          nec nulla. Vestibulum rhoncus ac ex sit amet fringilla. Nullam gravida
          purus diam, et dictum <a>felis venenatis</a> efficitur. Aenean ac{" "}
          <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
          sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
          magna a neque. Donec dui urna, vehicula et sem eget, facilisis sodales
          sem.
        </div>
      </article>
    </div>
  );
};

Vom prelua numele utilizatorului de pe adresa URL folosind parametrii rutei.

Adăugați ruta profilului în router.

<Route path="/profile/:name">
  <Profile />
</Route>

În prezent pagina de profil poate fi accesată direct. Deci, pentru a face din acesta un traseu autentificat, creați o componentă de ordin superior (HOC) pentru a încheia logica de autentificare.

const withAuth = (Component) => {
  const AuthRoute = () => {
    const isAuth = !!localStorage.getItem("token");
    // ...
  };

  return AuthRoute;
};

Pentru a determina dacă un utilizator este sau nu autentificat, apucați jetonul de autentificare stocat în browser atunci când utilizatorul se conectează. Dacă utilizatorul nu este autentificat, redirecționați utilizatorul către pagina principală. Redirect componentă din React Router poate fi utilizată pentru a redirecționa utilizatorul către o altă cale.

const withAuth = (Component) => {
  const AuthRoute = () => {
    const isAuth = !!localStorage.getItem("token");
    if (isAuth) {
      return <Component />;
    } else {
      return <Redirect to="/" />;
    }
  };

  return AuthRoute;
};

De asemenea, puteți transmite alte informații utilizatorului, cum ar fi numele și ID-ul utilizatorului, folosind elemente de recuzită către componenta împachetată.

Apoi, utilizați withAuth HOC în componenta Profil.

import withAuth from "../components/withAuth";

const Profile = () => {
 // ...
}

export default withAuth(Profile);

Acum, dacă încercați să vizitați /profile/JohnDoe, veți fi redirecționat către pagina principală. Asta pentru că simbolul de autentificare nu este încă setat în spațiul de stocare al browserului dvs.

Bine, deci, să revenim la Navbar componentă și adăugați funcționalitățile de conectare și deconectare. Când utilizatorul este autentificat, afișați butonul Deconectare și când utilizatorul nu este conectat, afișați butonul Conectare.

// components/Navbar.js

const Navbar = () => {
	// ...
    return (
    	<nav
          className="navbar is-primary"
          role="navigation"
          aria-label="main navigation"
        >
        <div className="container">
        	{/* ... */}
            <div className="navbar-end">
            <div className="navbar-item">
              <div className="buttons">
                {!isAuth ? (
                  <button className="button is-white" onClick={loginUser}>
                    Log in
                  </button>
                ) : (
                  <button className="button is-black" onClick={logoutUser}>
                    Log out
                  </button>
                )}
              </div>
            </div>
          </div>
        </div>
        </nav>
    );
}

Când utilizatorul dă clic pe butonul de conectare, setați un simbol fals în spațiul de stocare local și redirecționați utilizatorul către pagina de profil.

Dar nu putem folosi componenta Redirecționare în acest caz – trebuie să redirecționăm utilizatorul programatic. Jetoanele sensibile utilizate pentru autentificare sunt de obicei stocate în cookie-uri din motive de securitate.

React Router are un withRouter HOC care injectează history obiect în recuzita componentei pentru a utiliza API-ul Istoric. De asemenea, trece actualizat match și location recuzită pentru componenta înfășurată.

// components/Navbar.js

import { NavLink, withRouter } from "react-router-dom";

const Navbar = ({ history }) => { 
  const isAuth = !!localStorage.getItem("token");

  const loginUser = () => {
    localStorage.setItem("token", "some-login-token");
    history.push("/profile/Vijit");
  };

  const logoutUser = () => {
    localStorage.removeItem("token");
    history.push("/");
  };
  
  return ( 
   {/* ... */}
  );
};

export default withRouter(Navbar);

Și voilà! Asta e. Ați cucerit și țara rutelor autentificate.

Consultați demo-ul live aici și codul complet din acesta repo pentru referinta ta.

Concluzie

Sper că până acum aveți o idee corectă despre modul în care funcționează rutarea în partea clientului în general și despre cum să implementați rutarea în React folosind biblioteca React Router.

În acest ghid, ați aflat despre componentele vitale din React Router, cum ar fi Route, withRouter, Link, și așa mai departe, împreună cu unele concepte avansate, cum ar fi rutele autentificate, care sunt necesare pentru a construi o aplicație.

Verificați React Router documente pentru a obține o prezentare mai detaliată a fiecărei componente.