de paul christophe

Cum să vă protejați rutele cu React Context

Cum sa va protejati rutele cu React
Fotografie de Antonina Bukowska pe Unsplash

Printre schimbările din Reacționează 16.3 este o nouă versiune stabilă a API context. Vom arunca o privire la modul în care funcționează construind un componentă a traseului protejat.

Ce este contextul?

Contextul este despre starea de încapsulare. Ne permite să transmitem date dintr-o componentă furnizor părinte către orice componentă abonată din arborele respectiv. Fără managementul statului, trebuie să „forăm” recuzită prin fiecare componentă pe parcurs.

Nu pentru asta este Redux?

da, Contextul funcționează similar cu modul în care componentele se pot conecta la starea globală a Redux. Cu toate acestea, un element nativ precum Context va fi adesea o soluție mai bună pentru aplicațiile mici și mijlocii care nu au nevoie de cheltuielile complexe ale Redux.

Noțiuni de bază

Există trei elemente în context:

  • createContext – Apelarea aceasta returnează o pereche de componente, Provider și Consumer.
  • Provider – o componentă care permite una sau mai multe Consumers pentru a vă abona la modificări.
  • Consumer —O componentă abonată la un furnizor

Să începem să construim

Vom construi o aplicație cu Două rute. Unul este o pagină de destinație cu acces global. Celălalt este o pagină de bord cu acces restricționat pentru utilizatorii conectați. Puteți găsi versiunea finală aici.

Încercați: accesați / tabloul de bord în timp ce sunteți deconectat. Conectați-vă și navigați liber între rute. De la tabloul de bord, deconectați-vă și vă va da afară la pagina de destinație.

Antet context

Pentru a demonstra funcționalitatea de bază a Contextului, să începem prin a construi o componentă de antet care ne permite să ne conectăm și să ne deconectăm. Mai întâi, creați contextul nostru într-un fișier nou.

/* AuthContext.js */
import React from 'react';
const AuthContext = React.createContext();

Exportați o componentă AuthProvider pentru a defini starea noastră (dacă utilizatorul este conectat) și pentru a transmite starea sa către value prop pe Provider. Vom expune pur și simplu AuthConsumer cu un nume semnificativ.

/* AuthContext.js */
...
class AuthProvider extends React.Component {  state = { isAuth: false }
  render() {    return (      <AuthContext.Provider        value={{ isAuth: this.state.isAuth }}      >        {this.props.children}      </AuthContext.Provider>    )  }}
const AuthConsumer = AuthContext.Consumer
export { AuthProvider, AuthConsumer }

În index.js, înfășurați aplicația noastră în AuthProvider.

/* index.js */import React from 'react';import { render } from 'react-dom';import { AuthProvider } from './AuthContext';import Header from './Header';
const App = () => (  <;div>    <AuthProvider>      <Header />    </AuthProvider>  </div>);
render(<App />, document.getElementById('root'));

Acum creați-ne Header și importați-ne AuthConsumer (Las stilul pentru claritate).

/* Header.js */import React from 'react'import { AuthConsumer } from './AuthContext'import { Link } from 'react-router-dom'
export default () => (  <header>    <AuthConsumer>    </AuthConsumer>  </header>)

Context Consumatorii trebuie să aibă un funcționează ca copilul lor direct. Aceasta va fi transmisă din valoarea noastră Provider.

/* Header.js */...export default () => (  <header>    <AuthConsumer>
      {({ isAuth }) => (        <div>          <h3>            <Link to="/">              HOME            &lt;/Link>          </h3>
          {isAuth ? (            <ul>              <Link to="/dashboard">                Dashboard              </Link>              <button>                logout              </button>            </ul>          ) : (            <button>login</button>          )}        </div>      )}
    </AuthConsumer>  </header>)

pentru că isAuth este setat la fals, doar butonul de autentificare va fi vizibil. Încercați să schimbați valoarea în true (va trece la butonul de deconectare).

Ok, să încercăm să schimbăm isAuth în cod. Vom trece o funcție de conectare și deconectare de la Provider.

/* AuthContext.js */...class AuthProvider extends React.Component {  state = { isAuth: false }
  constructor() {    super()    this.login = this.login.bind(this)    this.logout = this.logout.bind(this)  }
  login() {    // setting timeout to mimic an async login    setTimeout(() => this.setState({ isAuth: true }), 1000)  }
  logout() {    this.setState({ isAuth: false })  }
  render() {    return (      <AuthContext.Provider        value={{          isAuth: this.state.isAuth,          login: this.login,          logout: this.logout        }}      >        {this.props.children}      </AuthContext.Provider>    )  }}

Aceste funcții ne vor permite să comutăm starea noastră de autentificare în Header.

/* Header.js */...export default () => (  <header>    <AuthConsumer>      {({ isAuth, login, logout }) => (        <div>          <h3>            <Link to="/">              HOME            </Link>          </h3>
          {isAuth ? (            <ul>              <Link to="/dashboard">                Dashboard              </Link>              <button onClick={logout}>                logout              </button>            </ul>          ) : (            <button onClick={login}>login</button>          )}        </div>      )}    </AuthConsumer>  </header>)

Traseu protejat cu context

Acum, că am acoperit elementele de bază, să extindem ceea ce am învățat pentru a crea o componentă de traseu protejat.

Prima marcă Landing și Dashboard componentele paginii. Tabloul nostru de bord va fi vizibil numai atunci când utilizatorul este conectat. Ambele pagini vor fi la fel de simple, ca mai jos:

/* Dashboard.js */import React from 'react'
const Dashboard = () => <h2>User Dashboard</h2>
export default Dashboard

Acum să trecem la aceste pagini.

/* index.js */import React from 'react';import { render } from 'react-dom';import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';import { AuthProvider } from './AuthContext';import Landing from './Landing';import Dashboard from './Dashboard';import Header from './Header';
const App = () => (  <;div>    <Router>      <AuthProvider>;        <Header />        <Switch>          <Route path="/dashboard" component={Dashboard} />          <Route path="/" component={Landing} />        &lt;/Switch>      </AuthProvider>    </Router>  </div>);
render(<App />, document.getElementById('root'));

În această stare curentă puteți naviga la ambele / și /dashboard. Vom crea o componentă de rută specială care verifică dacă un utilizator este conectat sunat ProtectedRoute. Configurarea este similară cu cea a noastră Header componentă.

/* ProtectedRoute.js */import React from 'react';import { Route, Redirect } from 'react-router-dom';import { AuthConsumer } from './AuthContext';
const ProtectedRoute = () => (  <AuthConsumer>    {({ isAuth }) => (
    )}  </AuthConsumer&gt;);
export default ProtectedRoute;

Traseul privat va funcționa la fel ca un obișnuit react-router rută, așa că vom expune componenta și orice alte elemente de recuzită transmise la aceasta.

const ProtectedRoute = ({ component: Component, ...rest }) => (

Acum partea interesantă: vom folosi isAuth variabilă pentru a determina dacă ar trebui să redirecționeze sau să redea componenta rutei protejate.

const ProtectedRoute = ({ component: Component, ...rest }) => (  <AuthConsumer>    {({ isAuth }) => (      <Route        render={          props =>            isAuth             ? <Component {...props} />             : <Redirect to="/" />        }        {...rest}      />    )}  </AuthConsumer>)

În a noastră index fișier să importăm ProtectedRoute și folosiți-l pe ruta noastră de bord.

/* index.js */...
  <ProtectedRoute path="/dashboard" component={Dashboard} />

Minunat, acum avem rute protejate! Încercați să indicați browserul către /dashboard și urmărește-l înapoi la pagina de destinație.

Din nou, iată linkul pentru demo de lucru. Citiți mai multe despre Context din Documente oficiale React.