Как защитить свои маршруты с помощью React Context

1656634687 kak zashhitit svoi marshruty s pomoshhyu react

Пол Кристоф

1*wmwNRYeBumNlEKriJxLHjg
Фото Антонины Буковской на Unsplash

Среди изменений в React 16.3 есть новая стабильная версия API контекста. Мы посмотрим, как это работает, создав a защищенный компонент маршрута.

Что такое контекст?

Контекст касается состояния инкапсуляции. Это позволяет нам передавать данные от компонента родительского поставщика к любому предоплаченному компоненту вниз по дереву. Без управления состоянием нам часто приходится сверлить все компоненты на этом пути.

Не для этого ли Redux?

Да, Контекст работает так же, как компоненты могут подключаться к глобальному состоянию Redux. Однако нативный элемент, например Context, часто будет лучшим решением для малых и средних программ, которым не требуются сложные накладные расходы Redux.

Основные понятия

В контексте есть три элемента:

  • createContext – Вызов этого возвращает пару компонентов, Provider и Consumer.
  • Provider — Компонент, разрешающий один или более Consumers подписаться на изменения.
  • Consumer —компонент, подписанный на поставщика

Начнём строить

Мы создадим программу с помощью два маршруты. Один есть целевая страница с глобальным доступом. Другой есть страницу информационной панели с ограниченным доступом для авторизованных пользователей. Окончательную версию можно найти здесь.

Попробуйте: перейдите в /dashboard, выйдя из системы. Войдите и свободно перемещайтесь между маршрутами. Выйдите из информационной панели, и вы будете переброшены на целевую страницу.

Чтобы продемонстрировать базовую функциональность Context, давайте начнем с создания компонента заголовка, позволяющего нам входить и выходить. Сначала создайте наш контекст в новом файле.

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

Экспорт компонента AuthProvider чтобы определить наше состояние (или вошел пользователь) и передать его состояние value опора на Provider. Мы просто разоблачим AuthConsumer с содержательным названием.

/* 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 }

В index.js заверните наше приложение 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'));

Теперь создайте наш Header и импортировать наши AuthConsumer (Я оставляю стиль для ясности).

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

Контекст Потребители должны иметь a функционируют как их прямые дети. Это будет передано значение из нашего 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>)

Поскольку isAuth установлено значение false, будет видна только кнопка входа. Попробуйте изменить значение на true (это будет переключено на кнопку выхода).

Ладно, давайте попробуем переключиться isAuth в коде Мы передадим функцию входа и выхода из нашего 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>    )  }}

Эти функции позволят нам включить состояние авторизации 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>)

Защищенный маршрут с контекстом

Теперь, когда мы рассмотрели основы, давайте расширим то, что мы научились создать компонент защищенного маршрута.

Сначала сделать Landing и Dashboard компоненты страницы. Наша информационная панель будет видна только тогда, когда пользователь вошел в систему. Обе страницы будут такими же простыми, как показано ниже:

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

Теперь перейдем к этим страницам.

/* 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'));

В этом текущем состоянии вы можете перейти к обоим / и /dashboard. Мы создадим специальный компонент маршрута, который проверяет, вошел ли пользователь в систему ProtectedRoute. Настройки похожи на наши Header компонент.

/* 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;

Частный маршрут будет работать как обычный react-router route, поэтому мы откроем компонент и любые другие свойства, передаваемые ему.

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

Теперь самое интересное: мы будем использовать isAuth переменная, чтобы определить, должна ли она перенаправлять или воспроизводить компоненты защищенного маршрута.

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

В нашем index файл импортируем ProtectedRoute и используйте его на нашем маршруте панели управления.

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

Прекрасно, теперь у нас есть защищенные маршруты! Попытайтесь указать в браузере /dashboard и смотрите, как это возвращает вас на целевую страницу.

Опять же вот ссылка на рабочую демонстрацию. Узнайте больше о Context в официальных документах React.

Добавить комментарий

Ваш адрес email не будет опубликован.