Как настроить аутентификацию пользователей с помощью React, Redux и Redux Saga

ОБНОВЛЕНИЕ (12.02.2019): я недавно обновил этот проект, добавив в него самые последние маршрутизаторы реакции, то есть версию 4.3.1, которая является response-router-dom. Пожалуйста, зайдите в его репозиторий, чтобы увидеть изменения.

В своем предыдущем блоге я писал, как написать масштабируемую архитектуру на Node.js. Поскольку я использовал почтальона для тестирования работы этой платформы, я подумал, что было бы неплохо реализовать его клиентскую часть. Чтобы написать его клиентскую часть, я решил использовать следующий технический стек:

  • Реагировать
  • Redux
  • Redux-Saga
  • React Router

В этом посте предполагается, что вы уже знакомы с реакцией и основными концепциями Redux и Redux-Saga.

Начиная

Клонировать мой предыдущий репозиторий блога. CDв свою корневую папку и запустите npm install. Это установит все зависимости.

Во-вторых, установите mongodbв твоей машине. После установки запустите mongo server, используяmongodв вашем терминале, если он не запущен как служба на вашем компьютере.

Затем убедитесь, что пакет nodemon установлен на вашем компьютере глобально . Перейдите в папку на стороне сервера и запуститеnodemon index.jsдля запуска внутреннего сервера.

Теперь, когда наш бэкэнд запущен и работает, пора перейти к его реализации на стороне клиента.

Если вы еще не установили create-react-appзатем продолжайте установку, используя следующую команду.

npm install create-react-app -g

Эта команда установит create-react-appглобально .

Создайте проект

Пришло время создать проект. Использование:

create-react-app react-login

Это создаст новый проект с именем react-login. Идите вперед и cdв эту папку. Открыть свойpackage.jsonфайл в вашем любимом редакторе и добавьте следующие зависимости:

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

Теперь просто запустите:

npm install

который установит все упомянутые выше зависимости.

Индексный файл

Для начала откройте index.jsфайл и поместите в этот файл приведенный ниже код.

В этом коде мы импортируем reactи react-dom. Затем импортируем Routerи browserHistoryиз react-router. Они необходимы для целей маршрутизации, которые я буду использовать позже вroutes/index.jsфайл. Затем мы импортируем Provider, это используется для хранения дочерних компонентов.

configureStoreи routesэто то, что мы собираемся импортировать в следующий раз, и я реализую это через секунду. Просто импортируйте их как есть и используйте в этом файле, как показано выше.

Теперь наш индексный файл настроен.

Конфигурация магазина

Создайте новую папку под названием storeвнутри srcпапка. Внутри этой новой папки создайте файл с именем configureStore.js,и вставьте следующий код в этот файл.

Сначала мы импортируем createStore, которое будет использоваться createStore, и applyMiddlewareкоторое будет использоваться для применения промежуточного программного обеспечения к нашему магазину - в данном случае саги, но мы поговорим об этом позже в этом блоге - из redux.

Затем мы импортируем rootReducer- мы создадим это позже. А пока просто импортируйте его и используйте как есть. Затем следует функция configureStore, которая возвращает объект путем вызова createStoreфункции и передачи rootReducerв качестве параметра.

Наконец, export configureStoreделает configureStoreдоступным в index.jsсозданном ранее файле.

Теперь это не мешает нам создать src/reducersпапку, создайте файл index.js и вставьте в этот файл приведенный ниже код.

Этот файл отвечает за импорт остальных редукторов внутри папки редукторов, их объединение и экспорт, чтобы они были доступны для использования в configureStore.js. Мы внесем изменения в этот файл, когда добавим новые редукторы позже в этом блоге.

Файл маршрутизации

Время для файла маршрутов. Идите вперед и создайтеsrc/routesпапку и внутри этой папки создайте index.jsфайл. Теперь откройте его и вставьте приведенный ниже код.

Основная цель этого файла - обрабатывать маршрутизацию в нашем проекте. Импорт файлов React, Routeи IndexRoute. После этого нам понадобится контейнер, в данном случае я импортирую container/App, который мы скоро напишем. Далее RegisterPage, это компонент, и мы его тоже напишем.

В родительском элементе Route, когда домашний путь совпадает, мы просто визуализируем наш Appконтейнер. На IndexRouteпользователей будут видеть RegisterPageвыводимые внутри Appконтейнера.

Контейнер

Пришло время для контейнера. Идите вперед и создайте новую папку с именем container. Внутри этой папки создайте новый файл с именем App.jsи поместите в него приведенный ниже код.

Это довольно просто. Основное назначение этого файла - отрисовка остальных компонентов.{this.props.children}служит этой цели.

Постановка на учет

Пришло время registerPage. Создать новую папкуsrc/componentsи создайте компонент внутри папки компонентов с именемregisterPage.js. Вставьте приведенный ниже код в этот компонент.

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

Выход

После создания всех папок и файлов выше запустите npm startсвой проект и откройте//localhost:3000в вашем браузере. Вы должны увидеть результат ниже.

Щелчок здесь не приведет к перенаправлению на маршрут входа, который мы исправим дальше.

Заставить это работать

Маршрутизация

Чтобы маршрутизация работала, сначала создайте новый компонент внутри папки компонентов. Назовите его loginPage.jsи поместите код ниже внутри этого компонента.

Этот компонент очень простой. Он отображает базовый контент и ссылку для регистрации компонента.

Теперь откройте routes.jsфайл, который мы уже создали выше, и внесите следующие изменения.

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

Теперь обновите свой браузер, и вы должны loginPageсначала увидеть . Когда вы нажимаете на ссылку «Зарегистрироваться здесь», она registerPageдолжна отображаться.

Теперь у нас работают основные маршруты.

Вход и регистрация

Постановка на учет

Чтобы процесс входа в систему работал, я сначала займусь процессом регистрации, чтобы мы добавили некоторых пользователей в нашу базу данных. Итак, давайте продолжим, откроем components/registerPage.jsи обновим его следующим содержанием.

В этом файле вроде бы сейчас много кода, но все просто. Сначала мы импортируемconnectчтобы связать наш storeсregisterPageсоставная часть. Затем импортируемregisterUserActionкоторые мы напишем дальше.

Внутри renderфункции сначала я проверяю ответ сервера, если он существует, затем назначаю свойства успеха и сообщения, полученные от сервера. Это может быть отдельная функция, но для простоты я поместил их в renderфункцию.

Далее идет регистрационная форма. Когда пользователь нажимает кнопку регистрации, запускается onHandleRegistrationфункция, которая получает введенные пользователем данные из формы, иdispatch registerUserActionс их данными в качестве параметров. На следующем шаге мы напишем действия.

Чтобы приведенный выше код работал, нам нужно mapStateToProps, как мы делаем в нижней части компонента, а затем соединить его с registerPageкомпонентом в конце.

Действия

Пришло время добавить действия. Идите вперед и создайтеsrc/actionsпапка. Создатьindex.jsфайл и поместите в него приведенный ниже код.

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

Теперь продолжайте и создайте authenticationActions.jsфайл внутри той же папки и поместите в него приведенный ниже код.

Здесь я импортирую индексный файл, который экспортирует константы, а затем я export registrationUserActionвозвращаю объект с типом действия и данными пользователя. Тип действия в данном случае - REGISTER_USER. Это действие будет отправлено, когда пользователь пытается зарегистрироваться, и это действие будет доступно во всем нашем проекте, и мы будем слушать его в наших сагах.

Саги

Теперь мы находимся на этапе, когда мы можем внедрить наши саги в наш проект. Если вы новичок в Redux-Saga, я предлагаю вам пройти этот блог, прежде чем продолжить.

Если вы уже знаете о сагах, тогда создайте src/sagasпапка. Создатьindex.jsфайл и поместите в него приведенный ниже код.

В приведенном выше файле сначала я импортирую forkиз effectsиwatchUserAuthenticationfrom watchers- которого еще нет, но мы сделаем этот файл следующим. Затем я просто экспортирую функцию генератора и разветвляю watchUserAuthentication.

Теперь создайте watcher.jsфайл в той же папке, что и выше, и поместите в этот файл приведенный ниже код.

Опять же, я ввожу takeLatestэффект от redux-saga, затем registerSagaот authenticationSaga.js, который мы создадим дальше. Затем импортируйте actions/index.jsкак типы.

Я экспортирую функцию генератора, которая в основном наблюдает за REGISTER_USERдействием и вызывает registerSaga.

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

В этой саге я импортирую еще пару эффектов - putи callиз redux-saga. Затем registerUserServiceимпортируется из service/authenticationService.js. Я импортирую все действия как типы из actions/index.js. Затем я экспортирую функцию генератора registerSaga.

Эта функция отвечает за вызов registerUserService, который выполняет ajax-вызов на наш сервер для регистрации нового пользователя - о чем я напишу после этого шага. Он получает ответ registerUserServiceи помещает REGISTER_USER_SUCCESSдействие. Если есть ошибка, то ставит REGISTER_USER_ERRORдействие.

Импортируйте саги

Теперь, когда у нас есть саги, пора импортировать их в наш магазин. Откройте store/configureStore.jsи обновите его содержимое указанным ниже содержимым.

Здесь я ввожу createSagaMiddleware, rootReducerи rootSaga. Затем внутри configureStoreфункции я создаю новый sagaMiddlewareи передаю его createStoreиспользованию applyMiddlewareфункции. Наконец, я запускаю rootSaga.

Пришло время создать src/servicesпапку и создать новую первую службу. Назови этоauthenticationService.jsи поместите приведенный ниже код в эту службу.

Этот файл выполняет базовый запрос ajax с использованием API выборки с некоторыми параметрами и заголовком. Это довольно понятный сервис.

Редуктор

Теперь, когда мы делаем запрос к серверу, пришло время получить этот ответ в нашем компоненте. Для этого нам понадобится редуктор . Идите вперед и создайтеreducers/registerReducer.jsфайл и поместите в него приведенный ниже код.

Это простая функция-редуктор, которая получает состояние и возвращает новое состояние. Он проверяет REGISTER_USER_SUCCESSи REGISTER_USER_ERRORдействия, и возвращаются в новом состоянии в компонент.

Теперь идите и откройте src/reducers/index.jsфайл и обновите его следующим содержимым.

Здесь rootReducerя буду импортировать все редукторы, а затем объединить их перед экспортом. Именно этим я и занимаюсь register.

Запуск обновленного кода

Теперь мы закончили процесс регистрации. Пришло время обновить ваш браузер, перейти к маршруту регистрации и ввести некоторые данные. Если вы введете существующий адрес электронной почты, вы должны увидеть результат ниже.

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

Авторизоваться

Пришло время войти в систему пользователя после того, как он будет зарегистрирован. Давай и откройcomponents/loginPage.jsфайл и обновите его следующим содержимым.

Этот компонент почти такой же, как registerPage. Единственная разница в том, что он отправляетloginUserActionкоторые мы напишем дальше. Другое отличие состоит в том, что, если ответ от сервера будет успешным, я получу JWT token. Я храню этот токен в localStorage. Вы можете использовать другой метод, но в этом примере я использую этот подход.

Давай и открой actions/authenticationActions.jsи обновите его следующим содержанием.

Здесь я экспортирую новую loginUserActionфункцию с LOGIN_USERтипом действия и user payload.

Прежде чем двигаться вперед, откройте actions/index.jsфайл и обновите его содержимое следующим образом.

Теперь идите и откройте sagas/watchers.jsфайл и обновите его содержимое следующим образом.

Здесь я просто импортирую loginSagaи вызываю его, когда он получаетLOGIN_USERдействие.

У нас loginSagaеще нет. По этой причине откройтеsagas/authenticationSaga.jssaga и обновите ее содержимое следующим образом.

Здесь я импортирую дополнительную службу loginUserService, которую я буду реализовывать дальше, а затем экспортирую новую функцию генератора с именем loginSaga, которая выполняет почти то же самое, что и registerSaga.

Теперь откройте services/authenticationService.jsservice и обновите его содержимое следующим образом.

Здесь я добавляю loginUserService, который делает почти то же самое, что и registerUserService, то есть отправляет запрос ajax для входа пользователя.

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

Это делает почти то же самое, registerReducer- слушать LOGIN_USER_SUCCESSи LOGIN_USER_ERRORдействия, и возвращая новое состояние.

Теперь откройте reducers/index.jsфайл и обновите его содержимое с помощью кода ниже.

Здесь я импортирую loginReducerи комбинирую его, registerпрежде чем вернуть его как rootReducer.

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

Если вы вводите зарегистрированный адрес электронной почты, запрос должен быть успешным, но вы еще ничего не должны видеть, так как я не реализовал dashboardPageсоставная часть. Это будет доступно только после успешной аутентификации. Сказав это, давайте реализуем это.

Страница панели инструментов

Теперь создайте components/dashboardPage.jsкомпонент и поместите приведенный ниже код в этот компонент.

Это очень простой компонент - все, что он делает, это возвращает Dashboardтекст.

Теперь откройте routes/index.jsroute и обновите его содержимое следующим образом.

Здесь я делаю что-то новое. Сначала я импортирую dashboardPageи добавляю его в route. КогдаdashboardПри доступе к маршруту requireAuthфункция будет запущена. Эта функция проверяет, есть пользователь loggedInили нет. Чтобы проверить это, я ищуtokenin localStorage, который я сохранил в loginPageкомпоненте при успешном входе в систему. Если он существует, то dashboardPageотображается пользователю.

Теперь, когда вы обновляете страницу в своем браузере, вводите зарегистрированный адрес электронной почты и нажимаете Enter, вы должны увидеть следующие результаты.

Итак, это полная система входа в систему с использованием React, Redux и Redux-Saga. Если вы хотите увидеть весь проект, клонируйте этот репозиторий.

Надеюсь, вам понравился этот пост.