Headless WordPress – идея, которая используется все активнее в среде разработчиков. Я постараюсь раскрыть несколько тем, связанных с этим подходом. В частности, я покажу, как реализовать вход в приложение с помощью JWT.
Мы создадим простое приложение, которое позволит пользователям входить под своим логином. После входа мы выведем пользователю его данные.
Чтобы реализовать вход в приложение с помощью JWT, нам понадобится установить и активировать плагин JWT Authentication for WP REST API.
Подготовка приложения
Давайте создадим наше собственное приложение React с помощью Create React App. Открываем терминал (командную строку) и переходим к каталогу, в которой будет вестись разработка приложения.
Затем используем команду:
npx create-react-app my-app
Здесь вы можете заменить my-app на свое название. Это будет ваш каталог, в котором будет храниться весь код. Я решил назвать каталог headless.
Затем перейдите к этой папке. Запустить приложение можно уже сейчас с помощью команды npm start. Однако давайте сначала установим Gutenberg Components, npm-пакет @wordpress/components. Это позволит нам использовать различные компоненты в своем приложении.
Установить Gutenberg Components можно с помощью команды
npm install @wordpress/components
Поскольку пакет Gutenberg Components не включает в себя классы разметки, мы можем создать свое собственное руководство по CSS-стилям либо использовать существующие стилевые фреймворки, чтобы не тратить на это свое время. Если вы хотите создать приложение, которое будет использоваться в производстве – обязательно подумайте над тем, чтобы создать свою CSS-разметку.
Мы будем использовать Bootstrap 4 для стилей. Установить его можно с помощью команды:
npm install bootstrap
Также нам потребуется процессинг SASS (SCSS), потому нам нужно, чтобы наше приложение могло обрабатывать такие файлы. Для этого используется следующая команда:
npm install node-sass --save
Поскольку мы будем использовать стили Bootstrap и Gutenberg, мы можем удалить App.css и создать App.scss. Поместите следующее внутрь этого нового файла:
@import '~bootstrap/scss/bootstrap.scss'; @import '~@wordpress/components/build-style/style.css';
Теперь он будет компилироваться в файл CSS, который будет включать в себя стили как Boostrap, так и Gutenberg.
Нам нужно будет выполнять запросы POST и GET к нашему сайту WordPress, потому нам понадобится способ реализации этого. Вы можете использовать fetch из API браузера, либо библиотеку. Мы будем использовать библиотеку axios. Она устанавливается с помощью команды
npm install axios
Добавляем логику входа к нашему Headless WordPress
Откройте App.js, чтобы начать добавление логики входа. Мы будем проверять, является ли пользователь залогиненным или нет. Если нет, то мы покажем форму входа. В противном случае будет выводиться консоль.
Давайте скорректируем все импорты в приложении:
import React, { useState, useEffect } from 'react';
import './App.scss';
import '@wordpress/components/build-style/style.css';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
Не беспокойтесь по поводу появляющихся ошибок. Компоненты Dashboard и Login пока что не существуют, потому вы можете получать ошибки компиляции.
Теперь мы можем заменить функцию App на следующее:
function App() {
const [login, setLogin] = useState( '' );
const siteURL = 'yoursite_here';
useEffect(() => {
const localLogin = localStorage.getItem('login');
// If we have logged in, set it.
if ( localLogin ) {
setLogin( localLogin );
}
}, [login]);
return (
<div className="App container">
<h1>Headless WordPress</h1>
{
login && <Dashboard url={siteURL} token={login} setLogin={setLogin} />
}
{
! login && <Login url={siteURL} setLogin={setLogin}/>
}
</div>
);
}
Что мы здесь сделали:
- Мы использовали хуки React useState для глобальной обработки информации по логину
- Мы использовали хуки useEffect для обработки изменений в процессе входа в приложение
- Если мы залогинены, то в таком случае будет выведен компонент Dashboard
- Если мы не вошли в приложение, то тогда будет выведен компонент Login
С помощью useEffect наше приложение будет осуществлять вход нашего пользователя (если токен сохранен).
Мы передаем в оба компонента функцию setLogin, которая управляет глобальным состоянием для информации по входу в систему. Это позволит нам, к примеру, предлагать логаут для пользователей.
Создание компонента Login
Чтобы осуществить процедуру входа в наше приложение Headless WordPress для пользователя, нам нужно передать логин и пароль с первой попытки. Для этого нам нужна отдельная форма. Создадим папку components в папке с приложением и создадим файл Login.js.
Поместим в него следующий код:
import React from 'react';
import { TextControl, Button } from '@wordpress/components';
const axios = require('axios');
class Login extends React.Component {
constructor( props ) {
super( props );
this.state = { username: '', password: '' }
this.handleUsername = this.handleUsername.bind(this);
this.handlePassword = this.handlePassword.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
}
export default Login;
Мы импортируем Gutenberg-компоненты TextControl и Button, которые мы будем использовать для создания формы входа. У нас также будет еще 3 метода. Эти методы будут использоваться для хранения информации о состоянии входа в приложение, а также о логине пользователя.
Давайте создадим метод render и 2 метода для сохранения информации о состоянии входа. Вы увидите, как мы используем Gutenberg Components.
// ...
class Login extends React.Component {
// ...
handleUsername( username ) {
this.setState( { username } )
}
handlePassword( password ) {
this.setState( { password } )
}
render() {
return (
<form className="login" method="post">
<TextControl className="form-group" label="Username" value={ this.state.username } onChange={ (value) => this.handleUsername( value ) }
/>
<TextControl className="form-group" label="Password" type="password" onChange={ (value) => this.handlePassword( value ) }
/>
<Button isPrimary onClick={this.handleSubmit}>Login</Button>
</form>
);
}
}
Второй TextControl также получает password в качестве типа. Когда какой-либо из элементов управления изменится, он будет использовать соответствующий метод для сохранения информации о состоянии входа.
При нажатии на компонент Button мы будем пытаться войти в систему под пользователем. Давайте создадим этот метод сейчас:
//...
class Login extends React.Component {
//...
handleSubmit( e ) {
e.preventDefault();
const _this = this;
axios.post( this.props.url + '/wp-json/jwt-auth/v1/token/',
{
username: this.state.username,
password: this.state.password
})
.then(function (response) {
if ( response.status === 200 ) {
const data = response.data;
localStorage.setItem( 'login', data.token );
_this.props.setLogin( data.token );
}
})
.catch(function (error) {
function strip_html_tags(str) {
if ((str===null) || (str===''))
return false;
else
str = str.toString();
return str.replace(/<[^>]*>/g, '');
}
alert( strip_html_tags( error.response.data.message ) );
});
}
// ...
}
Мы публикуем имя пользователя и пароль в REST-маршруте для токена jwt. Если пользователь существует, то нам будет возвращен этот токен. Затем мы внесем токен в локальное хранилище, чтобы мы могли получить его при обновлении.
Если этот REST-маршрут вернет нам какие-либо ошибки, мы отобразим их без HTML-тегов.
Все это позволит нашим пользователям войти в приложение WordPress Headless.
Создание компонента Dashboard
В нашем компоненте Dashboard мы будем выводить информацию о нашем пользователе, чтобы мы знали, что мы получили корректного пользователя.
Создаем файл Dashboard.js внутри каталога components и помещаем в него следующее:
import React from 'react';
const axios = require('axios');
class Dashboard extends React.Component {
constructor( props ) {
super( props );
this.state = { user: { } };
this.Logout = this.Logout.bind(this);
this.getCurrentUser = this.getCurrentUser.bind(this);
}
}
export default Dashboard;
Нам также понадобится здесь axios, поскольку мы будем получать информацию о текущем залогиненном пользователе. Мы хотим получить эту информацию как можно скорее, еще когда компонент монтируется.
// ...
class Dashboard extends React.Component {
// ...
componentDidMount() {
this.getCurrentUser();
}
getCurrentUser() {
const token = this.props.token;
const userURI = this.props.url + '/wp-json/wp/v2/users/me';
const _this = this;
axios({
method: 'POST',
url: userURI,
headers: { 'Authorization': 'Bearer ' + token }
}).then(function (response) {
if ( response.status === 200 ) {
const data = response.data;
_this.setState( {user:data});
}
})
.catch(function (error) {
_this.Logout();
});
}
}
Мы используем маршрут wp-json/wp/v2/users/me для получения информации о текущем пользователе. Для этого мы передаем заголовок Authorization с нашим Bearer токеном.
Если мы не передадим этот заголовок, то плагин JWT не сможет определить, какой пользователь вошел в приложение.
Давайте теперь выведем информацию о залогиненном пользователе:
// ...
class Dashboard extends React.Component {
// ...
Logout() {
localStorage.removeItem('login');
this.props.setLogin('');
}
render() {
const { nickname, first_name, last_name } = this.state.user;
return (
<div className="dashboard">
<button type="button" className="btn btn-danger" onClick={this.Logout}>Logout</button>
<div className="jumbotron">
Welcome { nickname }
I think your name is { first_name } { last_name}
</div>
</div>
);
}
}
У нас есть кнопка логаута, которая также будет использовать переданный метод setLogin. Поскольку мы задали логин в виде пустой строки, приложение выполнит повторный рендеринг и выведет форму входа.
Заключение
Headless WordPress постепенно становится новым стандартом. Вы можете создать такое веб-приложение, которое легко можно будет впоследствии преобразовать в Android или iOS-приложение. Пакет Gutenberg Components значительно экономит время и силы.
Источник: https://www.ibenic.com