text Wordpress REST Full Api + React

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了text Wordpress REST Full Api + React相关的知识,希望对你有一定的参考价值。

1. Устанавливаем WP
2. Идем в themes и создаем тему
3. В теме нужны только: index.php, screenshot.png, style.css
4. Актиируем тему в админ панели
5. Устанавливаем плагин All in one migration из админки
6. Устанавливаем плагин для браузера Postman
7. Качаем плагин для WP JSON Basic Authentication 
(https://cmscafe.ru/docs/wordpress/rest-api/816-wp-rest-api-nastrojka-i-ispolzovanie-bazovoj-autentifikatsii)
Устанавливаем через копирование плагина в папку и далее через админ панель WP
8. Устанавливаем npm, nodejs если их еще нет
9. Ставим глобально возможность устанавливать приложения на react: npm install -g create-react-app
(https://reactjs.org/tutorial/tutorial.html)
10. Встаем в папку с темой и создаем приложение: create-react-app frontend
11. Проверяем структуру: /themes/ТЕМА/frontend, переходим в каталог
12. Стартуем проект npm run start, должен открытся браузер с приветствием от react
13. Билдим проект: npm run build, проверяем структуру папки build

deploy
================
14. Добавим зависимость renamer: npm install --save-dev renamer
15. Дополняем json в секции scripts
"build": "react-scripts build&&npm run build-rename",
"build-rename": "npm run build-rename-js&&npm run build-rename-css",
"build-rename-js": "renamer --regex --find \"main\\.[^\\.]+\\.\" --replace \"main.\" build\\static\\js\\*",
"build-rename-css": "renamer --regex --find \"main\\.[^\\.]+\\.\" --replace \"main.\" build\\static\\css\\*"
Теперь js и css файлы будут избавлятся от хеша в имени
16. Создаем в папке public: css, fonts, images, js
17. Билдим проект: npm run build, проверяем имена файлов: main.css, main.js в папке static
18. Содержимое build копируем в папку с темой
19. В index.php заносим содержимое index.html
20. Правим пути для подключаемых файлов. Функция WP get_template_directory_uri() вернет путь к теме
Пример: 
<link href="<?= get_template_directory_uri() ?>/static/css/main.css" rel="stylesheet">
<script type="text/javascript" src="<?= get_template_directory_uri() ?>/static/js/main.js"></script>
21. Пробуем запустить проект на deploy

postman
================
22. Получим путь к картинке для приложения
23. В app.js добавим тег <img src="" />
24. Загрузим картинку через админ панель WP (медиафайлы)
25. Идем в postman, на вкладке Authorization выполняем авторизацию (как созданный пользователь в WP)
26. Тип авторизации Basic Auth
27. На http://v2.wp-api.org/ забираем пример для получения JSON /wp-json/wp/v2/posts
28. По аналогии выполняем в postman тот же GET запрос, но с мedia /wp-json/wp/v2/media
27. Идем в документацию http://v2.wp-api.org/reference/media/ и видим описание структуры JSON
28. source_url - это путь к картинке, забираем его из postman
29. Прописываем в тег <img> нормальный путь

bootstrap
================
30. С https://react-bootstrap.github.io/components/buttons/ копируем пример кнопки <Button>Default</Button>
31. Вставляем компонент в app.js
32. Устанавливаем зависимость npm install --save react-bootstrap
33. Качаем bootstrap, т.к. зависимость - это только js, а нужен еще css
34. Вытаскиваем bootstrap.min.css  и ложим ее в public/css
35. Подключаем через %PUBLIC_URL% в файле index.html
<link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.min.css">
36. На deploy в index.php также подключаем
<link href="<?= get_template_directory_uri() ?>/css/bootstrap.min.css" rel="stylesheet">
37. Стартуем npm run start, проверяем локально - видим bootstrap-кнопку
38. Билдим npm run build, копируем в deploy, проверяем deploy "удаленно" - видим bootstrap-кнопку

SASS
================
39. Устанавливаем npm install --save npm-run-all для возможности запуска двух сценариев паралельно
(https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-css-preprocessor-sass-less-etc)
40. Из package.json из секции scripts убираем start и build
41. Вместо них добавляем четыре новые строки:
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js"
42. А строка build теперь будет такая:
"build": "npm-run-all build-css build-js build-rename"
43. Устанавливаем npm install --save node-sass-chokidar
44. Теперь создадим файл App.scss рядом с App.css с таким же содержимым.
45. Пробуем: npm run start и npm run build. Файл App.css теперь должен компилироватся из App.scss

Redux
================
--> https://www.youtube.com/playlist?list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_
46. Устанавливаем npm install redux --S / непосредственно redux
47. npm install redux-logger --S / логирует и выводит состояния в консоль браузера
(prev state, action и next state)
48. npm install redux-thunk --S / позволяет работать с асинхронными запросами 
(иначе будет ошибка: Action must be plain objects. Use custom middleware for async actions)
49. npm install redux-promise-middleware --S / позволит использовать объекты promise в redux
50. Дополним импортами файл index.js 
index.js - это точка входа в приложение (он содается автоматически и webpack знает, что он - точка входа)
import {Provider} from 'react-redux'; - подключаем redux, остальные импорты для redux вынесем в другой файл, сразу добавим его импорт:
import store from './store';
51. На том же уровне, что и index.js создадим store.js и подключим остальные импорты
import logger from 'redux-logger'; / логгер
import {createStore, combineReducers, applyMiddleware} from 'redux';
(createStore - возможность создавать store от redux (об этом ниже)
combineReducers - позволяет "объединять" редюсеры от redux (об этом ниже)
applyMiddleware - для работы с асинхронностью)
import thunk from 'redux-thunk';
import promise from 'redux-promise-middleware';

Router
================
52. nmp install react-router --save
53. npm install react-router-redux --save
(если router для react не будет работать с redux, то ставим nmp install react-router@3 --save 3-ю версию)
54. В index.js импортируем 
import {Router, Route, browserHistory} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
55. В store импортируем
import {routerReducer} from 'react-router-redux';

Проект
================
Пример проекта можно забрать в dropbox или по ссылке:
-->
56. В index.js подключаем константу для работы router
const history = syncHistoryWithStore(browserHistory, store);
57. Говорим redux, что его store находится в определенном месте
<Provider store={store}>
58. Говорим роутеру, что для history нужно использовать константу
<Router history={history}>
59. Говорим роутеру, что определенная ссылка будет работать с определенным компонентом
<Route path = '/' component={IndexPage} />
<Route path = '/about' component={AboutPage} />
60. Создадим эти компоненты-страницы в папке src/pages
src/pages/IndexPage
src/pages/AboutPage
61. В каждую из этих папок разместим три файла: js, scss, css. Например:
IndexPage.js - сам компонент
IndexPage.scss - файл для синтаксиса scss
IndexPage.css - файл, в который будет компилироваться scss (компилятор сам понимает, что нужно именно в него)
62. В каждом из компонента js импортируем:
import React, { Component } from 'react'; / для работы react и его класса Component
import './IndexPage.css'; - Чтобы компонента использовала именно этот файл стилей
import { Button } from 'react-bootstrap'; / компонента кнопки bootstrap
import { connect } from 'react-redux'; - для работы redux, обеспечивает взаимосвязь между состояниями и диспатчерами (об этом ниже)
import { setName } from '../../actions/userActions'; / подключим один файл с экшенами (об этом ниже)
import { Link } from 'react-router'; для работы компонента Link (создает ссылки)
63. Далее создадим структуру html через jsx-синтаксис. Пусть:
В h1 с классом title записывается текущее имя пользователя {this.props.user.name}
В компоненте-кнопке Button повешаем на клик функцию, меняющую имя пользователя {this.props.writeName('Дядя Петя')}
В компоненте-ссылкке Link пропишем переход на страницу to='/about'
Обо всем этом - ниже

Redux: экшены и редюсеры
================
67. Создадим экшен-файл userActions.js / экшены изменяют редюсеры (см. ниже) - по сути меняют пропсы
Внутри этого файла экспорируем функцию, которая возвращает диспатчер. 
Диспатчер всегда состоит из типа (SET_NAME) и его payload - объект со свойствами.
В нашем случае экшен будет возвращать асинхронный запрос через объект Promise (ассинхронность добивается для примера через setTimeout - потоки данных разделятся и redux поймет, что это асинхронность)
Таким образом, при отрабатывании экшена setName(name) мы возвращаем диспатчер типа SET_NAME и его payload - набор свойств
67. Создаем каталог с редюсерами src/reducers / редюсеры хранят состояния (пропсы), реагируют на диспатчер от экшена
В нем будут лежать редюсеры, которые возвращают состояния по принятому экшену. Также в нем хранятся значения по-умолчанию.
68. Создадим один редюсер userReducer как константу. Значения по-умолчанию сразу пропишем в принимаемый аргумент-state:
state = {name: 'Тётя Мотя'}
Через конструкцию switch мы просматриваем поступившие экшены. Т.к. мы будем иметь дело с асинхронными запросами, то к каждому экшену нужно добавить следующее:
_FULFILLED - запрос прошел успешно
_REJECTED - что-то пошло не так
При отлавливании нужно экшена мы сразу возвращаем нужное свойство из payload, которое с этим экшеном и пришло.
Конструкция ...state позволяет прокинуть значение по умолчанию в текущий объект (затем что-то из него можно перезаписать, что и происходит в примере)
Экспортируем редюсер через export default userReducer;
68. Идем в store.js и принимаем на импорт import userReducer from './reducers/userReducer';
69. store.js должен возвратить нам хранилище store. Это делается через
export default createStore(combineReducers({userReducer, routing:routerReducer}), window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), applyMiddleware(logger, thunk, promise()));
combineReducers позволяет объединять редюсеры в один store. Тут у нас идет объединение userReducer с роутером.
В этой же строке имеется усилитель. Суть усилительных middleware функций, взять входные данные, добавить что-то и передать дальше.
Этой строки мы еще коснемся чуть дальше.
70. Вернемся в IndexPage. Нам нужно подружить экшены и редюсеры.
Создаем константу mapStateToProps / Эта штука возвращает состояния в пропсы реакта. 
Таким образом, когда мы хотим получить текущее имя пользователя (this.props.user.name в теге h1) - то мы получаем объект user из редюсера state.userReducer
71. Создаем константу mapDispatchToProps / В ней пропишем нужный экшен для смены имени пользователя. 
Эта константа говорит, что действие writeName - это диспатчер, который образуется при отрабатывании экшена setName 
72. Далее экспортируем connect между состояниями и диспатчерами для данного компонента
export default connect(mapStateToProps, mapDispatchToProps)(IndexPage);
73. Теперь можно проверить саму страницу npm run start
Мы видим значение по-умолчанию. this.props.user.name, его мы задали в редюсере, а теперь мы его видим как пропс от реакта
При нажатии на кнопку Change name происходит вызов функции writeName. writeName - это вызов диспатчера, который вызывает экшен setName
setName имеет асинхронность, поэтому редюсер встречает его не по типу SET_NAME, а по двум дополненным другим: 
"SET_NAME_FULFILLED"
"SET_NAME_REJECTED"
Редюсер меняет значение name, которое прислал ему экшен в payload

Проверка роутера
================
74. Если мы создадим компонент AboutPage, аналогично IndexPage, то роутинг у вас уже работает )

Redux DevTools
================
75. Дает отличный инструментарий для работы с redux через дополнение к браузеру chrome
Именно для его работы нужны остальные параметры в createStore

Wordpress-плагины, сниппеты
================
76. FakerPreess - генерирует посты и др., для того, чтобы не забивать их руками.
77. К каждому посту можно прикрепить картинку-thumbnail
Создаем файлик featuries.php в папке с темой, прописываем 
if ( function_exists( 'add_theme_support' ) ) {
	add_theme_support( 'post-thumbnails' );
}
Теперь к каждому посту можно добавить картинку.
Чтобы в json приходил нормальный путь к данной картинке - установим better rest api featuries images
78. Установим плагин Advanced Custom Fields (из админки). Оф. сайт https://www.advancedcustomfields.com/
Это позволит работать с дополнительными полями в постах
79. Добавим к этому плагину аддон https://wordpress.org/plugins/acf-to-rest-api/
Нужно скачать, разархивировать в папку с плагинами WP и активировать плагин.
Теперь мы можем видеть свойство дополнительных полей в json ответе (объект acf)

WP админка (опции темы), Redux Framework
================
80. Устанавливаем плагин для подключения опций в тему
(https://helpstring.wordpress.com/2015/01/10/getting-started-with-redux-framework-introducing-it-and-integrating-it-into-your-theme/)
Демо: https://demo.redux.io
Можно воспользоватся ГЕНЕРАТОРОМ (https://wp-best.ru/frejmvork-redux-dlya-sozdaniya-optsij-temy.html)
81. Идем в каталог с установленными плагинами \plugins\redux-framework\sample и копируем каталог sample в папку с темой 
82. В sample-config.php находятся примеры, которые можно использовать для подключения нужных полей-опций
(https://docs.reduxframework.com/category/core/fields/)
83. barebones-config.php - файл конфигурации для темы. В секции START Basic Fields можно добавить нужные поля
84. Подключим конфиг е теме в файл functions.php 
require_once( dirname( __FILE__ ) . '/sample/barebones-config.php' );
85. Создадим свой endpoint для получения опций темы
(http://oddstyle.ru/wordpress-2/stati-wordpress/pishem-svoyu-konechnuyu-tochku-wp-rest-api-za-2-minuty.html)
(https://tomjn.com/2017/01/23/writing-wp-rest-api-endpoint-2-minutes/)
// Create your endpoint WP REST API to receive theme options (ReduxFramework plugin)
function get_redux_framework_theme_options() {
	return get_option( 'redux_deckline' );
}
add_action( 'rest_api_init', function () {
	register_rest_route( 'wp/v2', '/redux-theme-options/', array(
		'methods'  => 'GET',
		'callback' => 'get_redux_framework_theme_options'
	) );
} );
86. Теперь мы можем получить данные в postman по ссылке http://deckline/wp-json/wp/v2/redux-theme-options

WP API
================
87. Прокидываем свойства из полей катомной админки ReduxFrameworx в RestApi
Устанавливаем:
https://www.npmjs.com/package/wpapi
88. На той же странице можно посмотреть как делаются Custom Routes. Используя свою endpoint (см. выше) - прокидываем свой кастомный роутер
wp.adminData = wp.registerRoute('wp/v2', '/redux-theme-options/');
89. Теперь функция wp.adminData() будет возвращать нам опции админки redux framework
Можно создать получение любых постов, например по ссылке http://deckline/wp-json/wp/v2/posts?categories=2
wp.categories2get = wp.registerRoute('wp/v2', '/posts?categories=2/');
 
Переменные среды Environment Variables
================
(https://habrahabr.ru/company/plarium/blog/326520/ - раздел "переменные окружения")
(https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#advanced-configuration)
90. В папке frontend (корневая директория) создаем файл .env.development
91. Включаем браузер по умолчанию: BROWSER: env var
canary:
BROWSER=C:\Users\Genbo\AppData\Local\Google\Chrome SxS\Application\chrome.exe
Отключаем запуск браузера:
"BROWSER=none


以上是关于text Wordpress REST Full Api + React的主要内容,如果未能解决你的问题,请参考以下文章

构建LNMP+WordPress

自定义Wordpress中的内容

我们应该在Rest full services中使用啥JSON空白数组或404错误代码

Wordpress REST API (wp-api) 404 错误:无法访问 WordPress REST API

WordPress 网站上的 W3C 错误:属性 src-large、src-full、src-medium “此时元素 img 上不允许”

如何为WordPress主题添加一个返回顶部按钮