Рубрики
Без рубрики

Многоразовые, ограниченные маршруты с Redux, React и Ract React Router V4

Разве это не было бы круто, если бы мы могли бы сделать наше приложение автоматически ограничивать пользователей получить доступ к контенту на основе состояния авторизации в нашем магазине Redux?

Автор оригинала: Elliot Plant.

Этот эпизод привел к вам буквой «R»

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

Иногда мы даже будем ограничивать контент потому что Пользователь вошел в систему. Это не имеет смысла перейти на страницу входа в систему, если мы уже вошли в систему, это будет?

В сложных приложениях мы могли бы ограничить содержание на основе сложных уровней авторизации. Базовый пользователь не должен иметь доступ к панели администратора, но администратор должен иметь возможность просматривать все. Даже Подробнее Комплексные приложения, мы могли бы ограничить контент на основе набора разрешений доступа. Дизайнер может быть разрешен для редактирования кода, и инженер не может быть разрешен для редактирования конструкций.

Все эти ограничения основаны на состоянии аутентификации нашего приложения. Если мы используем Redux, то состояние должно быть в магазине redux приложения. Разве это не было бы круто, если бы мы могли бы сделать наше приложение автоматически ограничивать пользователей получить доступ к контенту на основе состояния авторизации в нашем магазине Redux?

#Codegoals.

Мы хотим сделать комментарии React, которые действуют как React Router <Маршрут/> Компонент, но подключен к нашему магазину Redux и перенаправить пользователям в безопасное место, если они пытаются получить доступ к ограниченному контенту.

К концу поста мы сможем написать код JSX, как это:


  ...
  
  
  ...

Где . Защищены Компонент расположен в /защищен в Доступно только для пользователей, которые вошли в систему. И наоборот Вход Компонент в /Вход в Доступно только для пользователей, которые являются не Вошел в систему. Я охвачу более продвинутые случаи, такие как уровни администратора, и авторизация на основе функций в будущем в будущем блоге, но эти сообщения будут основаны на коде, который мы пишем в этом руководстве.

Что ты знаешь

Чтобы получить максимальную отдачу от этого урока, вы должны иметь некоторое основное знакомство с реакцией, Redux и React Router V4.

Обучение React имеет пример Аутентификация с React Router V4 , но я настоятельно рекомендую проверить Учебник Тайлера Макгинниса на здание этого примера. Его видео особенно полезно, и мы будем следовать подобным путем, но с добавлением Redux

Чтобы узнать основы Redux с реагированием, возьмите читать на Это руководство Мигель Морено. Концепции, которые мы будем использовать здесь соединить , MapstatetoProps и mapdispatchtopops Отказ

TL; доктор

Последний код из этого учебника доступен на My Github Page Отказ Не стесняйтесь вилить это и, если вы найдете любые ошибки, сделайте запрос на тягу!

Настраивать

Огоненьтесь Create-React-App Чтобы создать новую папку проекта под названием Redux-Restricted-маршруты :

create-react-app redux-restricted-routes
cd redux-restricted-routes

Если вы не использовали Create-React-App Раньше установите его с помощью NPM Установить -G Create-React-App Отказ

Как только мы в проекте, мы должны быть в состоянии бежать

yarn start

Если вы видите экран по умолчанию «Create React App» в вашем веб-браузере, вы находитесь на правильном пути!

Создание экрана по умолчанию rac app app

Давайте маршрутим!

Теперь пришло время добавить в некоторые маршруты. Давайте использовать пряжу, чтобы добавить React-Router-DOM :

yarn add react-router-dom

Этот пакет обрабатывает маршрутизацию для проектов браузера, но большая часть кода, которую мы здесь используем сегодня, будут применяться для реагирования на родных и реагировать на проекты VR.

Прежде чем мы начнем маршрутизацию, нам нужно сделать некоторые компоненты для маршрута к Отказ Сделать файл под названием SRC/Компоненты/Pages.js и добавьте эти пять компонентов:

// src/components/pages.js

import React from 'react'

export const Home = () => 

Home

export const Public = () =>

Public

export const Protected = () =>

Protected

export const Login = () =>

Login

export const Logout = () =>

Logout

Чтобы использовать маршрутизатор, нам нужно будет предоставить Броситон (как Маршрутизатор ) Компонент из Реагистрационный маршрутизатор в корне нашего приложения. Мы настроим маршруты на наши страницы, используя Маршрут Компонент и добавить Ссылки навигаться к ним. Идите вперед и замените содержимое SRC/App.js С базовым компонентом маршрутизации:

// src/App.js

import React from 'react'
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import {Home, Public, Protected, Login, Logout} from './components/pages'

export default function App() {
  return (
      
        
  • Home
  • Public Page
  • Protected Page
  • Login Page
  • Logout Page
) }

Теперь давайте отправимся в браузер, и мы увидим, что мы можем доехать между нашими простыми страницами!

Мини-маршруты

Вход и Выход из системы Страницы на самом деле не регистрируют нас в или нет, но мы сможем исправить это после добавления redux.

Инициализация Redux.

Redux – это простое, но мощное состояние государственного управления, который мы будем использовать для управления нашим зарегистрированным состоянием/OUT. Продолжай и добавьте Redux в проект с помощью:

yarn add redux

В SRC Папка, давайте создадим каталог под названием redux и файл под названием Actions.js в новой папке. Затем давайте добавим эти два типа действий в Actions.js файл:

// src/redux/actions.js

// Action Types
export const LOG_IN_USER = 'LOG_IN_USER'
export const LOG_OUT_USER = 'LOG_OUT_USER'

Поскольку единственное состояние, которое мы заботимся о том, вошел ли пользователь в системе или нет, это единственные действия, которые нам понадобятся.

Чтобы облегчить наше будущее, давайте сделаем некоторые функции создателя действия для облегчения процесса входа в систему и добавить их в SRC/Redux/Actions.js файл:

// src/redux/actions.js

// Action Types
export const LOG_IN_USER = 'LOG_IN_USER'
export const LOG_OUT_USER = 'LOG_OUT_USER'

// Action Creators
export function logInUser() {
  return { type: LOG_IN_USER }
}
export function logOutUser() {
  return { type: LOG_OUT_USER }
}

Для того, чтобы справиться с этими действиями, нам понадобится редуктор. Рядом с вашим Actions.js Файл в SRC/Redux Создать Редукторы.js Файл с этим редуктором Auth:

// src/redux/reducers.js

import {LOG_IN_USER, LOG_OUT_USER} from './actions'

// Reducer for handling auth actions
export function authReducer(state = { isAuthed: false }, action) {
  switch (action.type) {
    case LOG_IN_USER:
      return {
        ...state,
        isAuthed: true
      }
    case LOG_OUT_USER:
      return {
        ...state,
        isAuthed: false
      }
    default:
      return state
  }
}

Все это редуктор делает обновление Изящно часть нашего государства, когда она видит Log_in_user и Log_out_user Действия.

Наконец, давайте будем использовать этот редуктор, чтобы сделать магазин. Создать store.js Файл в SRC/Redux Папка и инициализировать магазин с нашим редуктором:

// src/redux/store.js

import {combineReducers, createStore} from 'redux'
import {authReducer} from './reducers'

const reducers = combineReducers({
  auth: authReducer,
})

const store = createStore(reducers)

export default store

Этот файл использует Createstore Методы Redux, чтобы сделать магазин Redux из нашего редуктора Auth. Используя Коммунатории Функция – это сверхугольника, но в ваших будущих приложениях вы, вероятно, будете иметь более одного редуктора.

Мы экспортируем этот магазин, чтобы мы могли подключить его к Redux с React-redux упаковка.

Подключение Redux для реагирования

К счастью для нас, React-redux Пакет NPM сделает все тяжелые подъема, нам нужно сделать наше приложение Action Award о нашем магазине Redux. Добавьте этот пакет в проект, запустив:

yarn add react-redux

Этот пакет дает нам Провайдер Компонент, который позволяет компонентам в нашем приложении доступа к нашему магазину. Добавьте Провайдер Внутри вашего Приложение составная часть:

// src/App.js

import React from 'react'
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import {Home, Public, Protected, Login, Logout} from './components/pages'
import {Provider} from 'react-redux' // Don't forget the import!
import store from './redux/store' // Import store too

export default function App() {
  return (
     {/* <- Here */}
      
        
  • Home
  • Public Page
  • Protected Page
  • Login Page
  • Logout Page
) }

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

Теперь давайте получим некоторую индикацию нашего зарегистрированного статуса. Сделать SRC/Компоненты Затем папка создать файл под названием Authindicator.js С помощью этого компонента JSX:

// src/components/AuthIndicator.js

import React from 'react'

const AuthIndicator = ({isAuthed}) =>(
  isAuthed
    ? 

Welcome! You are logged in

:

You are not logged in. Please log in to view protected content

)

Этот компонент просто требует одного опоры и говорит нам, вошли ли мы в системе или нет. Для подключения этого компонента к нашему магазину Redux мы используем React-redux ‘s соединить Метод, который может принять MapstatetoProps функция. Эта функция позволяет нам решить, как мы хотим сказать нашему компоненту об изменениях в магазине redux, и имеет дополнительное преимущество предотвращения повторных рендеров, если часть состояния, которую мы проходим к нашему компоненту, не изменились.

// src/components/AuthIndicator.js

import React from 'react'
import {connect} from 'react-redux'

const AuthIndicator = ({isAuthed}) =>(
  isAuthed
    ? 

Welcome! You are logged in

:

You are not logged in. Please log in to view protected content

) const mapAuthStateToProps = ({auth: { isAuthed }}) => ({isAuthed}) export default connect(mapAuthStateToProps)(AuthIndicator)

Теперь, когда наш Authindicator знает о нашем магазине Redux, давайте добавим его в приложение:

// src/App.js

import React from 'react'
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import {Home, Public, Protected, Login, Logout} from './components/pages'
import {Provider} from 'react-redux'
import store from './redux/store'
import AuthIndicator from './components/AuthIndicator' // Don't forget the import!

export default function App() {
  return (
    
      
        
{/* <- Here */}
  • Home
  • Public Page
  • Protected Page
  • Login Page
  • Logout Page
) }

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

Нежелательный

Идеально! Приложение знает, что мы не вошли в систему. Давайте добавим способ изменить это.

Мы собираемся добавить некоторую сложность к страницам входа и выхода из системы, поэтому давайте удалим их из SRC/Компоненты/Pages.js и построить их в свои файлы.

Создать SRC/Компоненты/login.js Файл с этим функционалом Вход составная часть:

// src/components/Login.js

import React from 'react'
import {connect} from 'react-redux'
import {logInUser} from '../redux/actions'

// A functional component that requires a logInUser function as a parameter
const Login = ({ logInUser }) => (
  

Login

) // Gives the login button ability to dispatch to store export default connect(null, {logInUser})(Login)

Обратите внимание, что компонент входа требуется один опорный, Логин функция, и она получает эту опору от соединить Второй аргумент метода (в целом называется mapdispatchtoprops ). Также обратите внимание, что мы проезжаем null Как первый аргумент для соединить (Как правило, называется MapstatetoPOOPs ) Поскольку наш компонент входа в систему не заботится о состоянии приложения.

Пока мы на этом, давайте создадим Выход из системы Компонент в новом SRC/Компоненты/logout.js файл:

// src/components/Logout.js

import React from 'react'
import {connect} from 'react-redux'
import {logOutUser} from '../redux/actions'

// A functional component that requires a logOutUser function as a parameter
const Logout = ({ logOutUser }) => (
  

Logout

) // Gives the logout button the ability to dispatch to store export default connect(null, {logOutUser})(Logout)

Вы, вероятно, заметите, что этот компонент очень похож на Вход составная часть. Основное отличие в том, что вместо того, чтобы принимать Логин Пропор, это примет LogoutUser пропры

Давайте добавим наши новые компоненты в наше приложение в /src/app.js :

// src/App.js

import React from 'react'
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import {Home, Public, Protected} from './components/pages' // Remove Login, Logout
import {Provider} from 'react-redux'
import store from './redux/store'
import AuthIndicator from './components/AuthIndicator'
import Login from './components/Login' // Add import to new file
import Logout from './components/Logout' // Add import to new file

export default function App() {
  return (
    
      
        
  • Home
  • Public Page
  • Protected Page
  • Login Page
  • Logout Page
) }

Теперь отправляйтесь в ваш веб-браузер и посмотрите, работает ли наша аутентификация:

Войти/Выйти

Потрясающие! Наше Authindicator показывает нам, вошли ли мы вошли или нет, и наш Вход и Выход из системы Компоненты позволяют войти и выйти из системы. В реальном приложении этот процесс в процессе, вероятно, включает проверку токена с вашим сервером, но эта упрощенная версия достаточно для наших целей маршрутизации.

Один яркий недостаток в том, что мы можем пойти в /Выход из системы и /защищен Страницы, даже если мы не вошли в систему … Давайте изменим это.

Маршрутизатор, встреча redux

Наконец, что мы все ждали! Пришло время подключить свой роутер к Redux.

Давайте создадим компонент «переключатель», который либо отображает предоставленный компонент или перенаправить пользователя. Мы будем использовать React-Router-DOM ‘s Перенаправить Компонент, который, при виновке, просто перенаправляет пользователя к к Маршрут, очень похоже на код перенаправления 304 с сервера. Давайте поместим этот компонент в новом файле под названием SRC/RestrictedRoutemaker.js :

// src/restrictedRouteMaker.js

import React from 'react'
import {Redirect} from 'react-router-dom'

// HOC to either render the given component or redirects based on the `restricted` prop
const RedirectSwitch = ({ component: Component, restricted, redirectPath, ...rest }) => (
  restricted
    ? 
    : 
)

Это компонент более высокого порядка (HOC), который принимает компонент для условно визуализации как один из его реквизитов. Если Ограниченный опора правда мы визуализировать Перенаправить и таким образом перенаправлять пользователя. Если Ограниченный это ложь мы визуализировать Компонент без каких-либо изменений. Мы могли бы использовать этот новый компонент в Маршрут Компонент, как это:

 (
    
  )}
/>

Мы говорим Маршрут Компонент, который, если наш пользователь идет к /защищен Маршрут, мы должны сделать Redirectswitch это ограничено на основе некоторых Изящно Переменные и перенаправить пользователей на /Вход Маршрут, если они есть Ограниченный или визуализация Защищены Если они нет.

И мы будем сделаны! Но подожди, титул сказал Многоразовый Маршруты. Ой. Этот код определенно не многоразовый. И нам придется выяснить, где получить Изящно в любом случае. Хм.

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

Сначала мы можем видеть, что наши Redirectswitch Компонент требует как минимум три реквизита: Компонент , Ограниченный и RedirectPath Отказ Эти реквизиты придут из трех разных мест. На внешнем слое API нашего конечного компонента должен быть таким же, как Маршрут поэтому пользователь может предоставить Компонент опоры там. Ограниченный Пропор должен быть рассчитан из нашего состояния, поэтому мы захотим использовать React-redux’s соединить Метод и MapstatetoProps Отказ Наконец, мы можем сделать наши ограниченные маршруты более многоразовыми, если мы вводим RedirectPath PROP с HOC, поэтому конечный пользователь не должен передавать его каждый раз.

... отдых опоры просто передается на Компонент Как оператор спреда, и это позволяет пользователю пропускать реквизиты полностью из Маршрут к оказанным Компонент Отказ

Давайте сделаем HOC, чтобы ввести RedirectPath Отказ Мы можем обернуть Redirectswitch Компонент в другом HOC делать только что:

// src/restrictedRouteMaker.js

// ...

// Adds `redirectPath` as an HOC injected prop to a RedirectSwitch
const addRedirectPathToSwitch = (redirectPath) => (props) => (
  
)

Выход этого HOC дает Redirectswitch что всегда перенаправляет до того же места. Например, мы могли бы сделать Loginrisheredswitch Компонент, который перенаправляет на /Вход как это:

const LoginRedirectSwitch = addRedirectPathToSwitch('/login')

Далее давайте будем использовать соединить рассчитать наши Ограниченный опоры от нашего государства. Нам нужно сделать MapstatetoProps Функция, так что используя наши Loginredirectswitch В качестве примера мы могли бы сделать:

const mapStateToAuthProps = ({auth: { isAuthed }}) => ({ restricted: isAuthed })
const ConnectedLoginRedirectSwitch = connect(mapStateToAuthProps)(LoginRedirectSwitch)

Это берет Auth.isauthed Часть состояния и передает его в наш коммутатор, как Ограниченный пропры Ваше государство может иметь JWT или какое-то другое указание о том, является ли пользователь аутентифицирован и авторизован, но, однако, вы рассчитываете, можете войти в этот MapstatetoProps функция.

Наконец, давайте обернуть наше соединить Выключатель ED внутри элемента маршрута:

// src/restrictedRouteMaker.js

// ...
import {Route, Redirect} from 'react-router-dom'

// ...
const makeSwitchRoute = (SwitchComponent) => ({ path, component: RenderComponent, ...rest }) => (
   }/>
)

Этот HOC позволяет нам взять наши InningleLoginredirectswitch Компонент и гнездо в нее в реактивный маршрутизатор Маршрут компонент, так что переключатель отображается, когда Маршрут путь соответствует. Мы могли бы использовать это так:

const AuthRestrictedRoute = makeSwitchRoute(ConnectedLoginRedirectSwitch)
// ...
  
// ...

Этот компонент будет соответствовать /защищен Маршрут и визуализацию Защищены Компонент, как нормальный Маршрут Если пользователь вошел в систему, и если они нет, он будет перенаправлять их на /Вход маршрут. Кроме того, он многоразовый! Мы могли бы поставить другой Authrestrictedroute Прямо рядом с этим:

const AuthRestrictedRoute = makeSwitchRoute(ConnectedLoginRedirectSwitch)
// ...
  
  
// ...

Обе маршруты ограничены пользователями, которые вошли в систему, и оба будут перенаправлены на /Вход Страница Если пользователь пытается получить доступ к маршруту до входа в систему. Cool, верно?

Но мы должны были пройти много обручей, чтобы настроить Authrestrictedroute составная часть. Можем ли мы сделать это легче, упаковывая все в одной функции?

Оптимизация с составным

Мы можем работать наш путь от Redirectswitch к Authrestrictedroute С каждой из функций мы ранее писали, чтобы построить эту обертку функции:

const restrictedRouteMaker = () => {
  const LoginRedirectSwitch = addRedirectPathToSwitch('/login')
  const mapStateToProps = ({auth: { isAuthed }}) => ({ restricted: isAuthed })
  const ConnectedLoginRedirectSwitch = connect(mapStateToProps)(LoginRedirectSwitch)
  const AuthRestrictedRoute = makeSwitchRoute(ConnectedLoginRedirectSwitch)

  return AuthRestrictedRoute
}

Это будет работать, если мы только хотеем сделать Authrestrictedroute Компонент, но мы заинтересованы в обобщении процесса.

Есть действительно только два уникальных значения, которые нам нужно сделать RestrictedRoute Компонент: RedirectPath и MapstatetoProps Итак, давайте сделаем нашу фабричную функцию принять эти два значения в качестве параметров:

const restrictedRouteMaker = (redirectPath, mapStateToRestricted) => {
  const LoginRedirectSwitch = addRedirectPathToSwitch('/login')
  const mapStateToProps = ({auth: { isAuthed }}) => ({ restricted: isAuthed })
  const ConnectedLoginRedirectSwitch = connect(mapStateToProps)(LoginRedirectSwitch)
  const AuthRestrictedRoute = makeSwitchRoute(ConnectedLoginRedirectSwitch)

  return AuthRestrictedRoute
}

Теперь, давайте будем использовать эти параметры, чтобы сделать обобщенные RestrictedRouteMaker :

const restrictedRouteMaker = (redirectPath, mapStateToRestricted) => {
  const RedirectSwitchWithPath = addRedirectPathToSwitch(redirectPath)
  const ConnectedRedirectSwitchWithPath = connect(mapStateToRestricted)(RedirectSwitchWithPath)
  return makeSwitchRoute(ConnectedRedirectSwitchWithPath)
}

И мы могли бы использовать эту функцию, чтобы сделать наши Authrestrictedroute :

const AuthRestrictedRoute = restrictedRouteMaker('/login', ({auth: { isAuthed }}) => ({ restricted: isAuthed }))

Или мы могли бы построить маршрут, который доступен только людям, которые не Авторизовал:

const NoAuthRestrictedRoute = restrictedRouteMaker('/', ({auth: { isAuthed }}) => ({ restricted: !isAuthed }))

Мы могли бы даже построить маршрут, который не доступен Джим, который сидит за столом по залу:

const NoJimRoute = restrictedRouteMaker('/somewhere', ({user: { email }}) => ({ restricted: email === 'jim@company.com' }))

Но мы можем сделать еще лучше! Обратите внимание, что RestrictedRouteMaker это просто серия функций, вызываемых с результатом предыдущей функции. Это именно то, что составить Функция из redux была сделана для. Это метод, который принимает серию функций и возвращает функцию, которая вызывает их друг на друге справа налево, подвергая исключению в качестве входа в возвращенную функцию. Давайте добавим созданную версию RestrictedRouteMaker нашему SRC/RestrictedRoutemaker.js файл:

// src/restrictedRouteMaker.js

// ...
import {connect, Provider} from 'react-redux'
import {compose} from 'redux'

// ...

const restrictedRouteMaker = (redirectPath, mapStateToRestricted) => compose(
  makeSwitchRoute,
  connect(mapStateToRestricted),
  addRedirectPathToSwitch
)(redirectPath)

Обратите внимание, что RedirectPath передается в состав на улице, потому что нам нужно передать его на AddredirectPathToSwitch Чтобы вызвать композицию.

Вот весь RestrictedRouteMaker.js файл:

// src/restrictedRouteMaker.js

import React from 'react'
import {connect, Provider} from 'react-redux'
import {compose} from 'redux'
import {Route, Redirect} from 'react-router-dom'

// HOC to either render the given component or redirect based on the `restricted` prop
const RedirectSwitch = ({ component: Component, restricted, redirectPath, ...rest }) => (
  restricted
    ? 
    : 
)

// Adds `redirectPath` as an HOC injected prop to a RedirectSwitch
const addRedirectPathToSwitch = (redirectPath) => (props) => (
  
)

// Component factory to wrap SwitchComponent inside a react-router Route
const makeSwitchRoute = (SwitchComponent) => ({ path, component: RenderComponent, ...rest }) => (
   }/>
)

// Wraps all our other components in a HOC factory function
export default (redirectPath, mapStateToRestricted) => compose(
  makeSwitchRoute,
  connect(mapStateToRestricted),
  addRedirectPathToSwitch
)(redirectPath)

Используя наш маршрут завод

Теперь мы можем использовать наш маршрутный завод, чтобы сделать некоторые ограничиваемые маршруты! Вернуться в app.js, давайте сделаем две ограниченные маршруты, по одному для выделенных маршрутов и один для несовместимых маршрутов:

// src/App.js

// ...
import restrictedRouteMaker from './restrictedRouteMaker'

// Create route with auth restriction that redirects to /login
const mapStateToAuthProps = ({auth: { isAuthed }}) => ({ restricted: !isAuthed })
const AuthRestrictedRoute = restrictedRouteMaker('/login', mapStateToAuthProps)

// Create route with no-auth restriction that redirects to /
const mapStateToNoAuthProps = ({auth: { isAuthed }}) => ({ restricted: isAuthed })
const NoAuthRestrictedRoute = restrictedRouteMaker('/', mapStateToNoAuthProps)

// ...

Теперь, давайте будем использовать наши маршруты, чтобы исправить разрешения на нашу Вход , Защищены и Выход из системы Страницы:

// src/App.js

import React from 'react'
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import {Home, Public, Protected} from './components/pages' // Remove Login, Logout
import {Provider} from 'react-redux'
import store from './redux/store'
import AuthIndicator from './components/AuthIndicator'
import Login from './components/Login' // Add import to new file
import Logout from './components/Logout' // Add import to new file
import restrictedRouteMaker from './restrictedRouteMaker'

// Create route with auth restriction that redirects to /login
const mapStateToAuthProps = ({auth: { isAuthed }}) => ({ restricted: !isAuthed })
const AuthRestrictedRoute = restrictedRouteMaker('/login', mapStateToAuthProps)

// Create route with no-auth restriction that redirects to home
const mapStateToNoAuthProps = ({auth: { isAuthed }}) => ({ restricted: isAuthed })
const NoAuthRestrictedRoute = restrictedRouteMaker('/', mapStateToNoAuthProps)

export default function App() {
  return (
    
      
        
  • Home
  • Public Page
  • Protected Page
  • Login Page
  • Logout Page
) }

Если мы отправимся в браузер, мы увидим, что если мы попытаемся пойти на Защищены или Выход из системы Страницы перед входить в систему, мы перенаправляемся на Вход страница! И наоборот, если мы попытаемся пойти на Вход Страница Когда мы уже вошли в систему, мы перенаправляемся на Главная страница. Эти новые маршруты сидят прямо рядом с обычным, неограниченным Маршрут S и вести себя то же самое с добавлением наших ограничений. Сладкий.

Ограниченная навигация

Заключение

Создав компонентный завод более высокого порядка, который соединяет наши маршруты к нашему магазину Redux, мы можем ограничить доступ к частям нашего приложения, основываясь непосредственно на нашем состоянии redux. Как мы только что увидели, это очень полезно для аутентификации, но его можно легко продлевать на другие ограничения. Что, если вы хотите сделать маршрут, ограниченный для пользователей, которые не дополняют ваши волосы? Это так просто, как:

const mapStateToComplimentProps = ({user: { hasComplimentedMyHair }}) => ({ restricted: !hasComplimentedMyHair })
const HairComplimentRestrictedRoute = restrictedRouteMaker('/not-fabulous', mapStateToComplimentProps)
// ...
  
// ...

Возможности безграничны. Теперь отправьте уверенность своих пользователей!

Первоначально опубликовано на github.com/elliotApplant