Создание пользовательского блока Гутенберга. Часть 10. Получение сообщений и компонентов более высокого порядка
В этой заключительной части серии руководств по пользовательским блокам Gutenberg мы узнаем, как использовать компоненты более высокого порядка для использования компонентов WordPress для выполнения запросов к сообщениям и другой основной информации WordPress.
В предыдущей части мы узнали о динамических блоках и закончили тем, что реализовали функциональность для ввода идентификатора сообщения и использования PHP для динамического получения сообщения и его отображения в интерфейсе и режиме предварительного просмотра. Ручной ввод идентификатора сообщения не является интуитивно понятным или удобным для пользователя. Гораздо лучше предоставить пользователю возможность выбирать или искать сообщения по заголовку сообщения и щелкать что-то, чтобы выбрать одно из них.
Одна часть решения этой проблемы довольно проста; как запрашивать сообщения из edit
функции вашего блока. У нас есть несколько вариантов для этого, и лучший вариант — использовать некоторые из так называемых компонентов более высокого порядка из WordPress. Вы также можете использовать методы браузера Javascript для выполнения вызова AJAX к WordPress REST API, используя, например, [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
или axios. WordPress фактически предоставляет собственную версию fetch
: apiFetch()
.
Другая часть решения этой проблемы зависит от вас; как представить список или выбор в нашем блоке. Как вы собираетесь представить список постов на выбор? В списке выбора флажков или переключателей? Или вы хотите предложить возможность поиска и, таким образом, внедрить решение для автозаполнения или фильтр? Должны ли вы разрешить выбор нескольких сообщений или только одного? Обычно вы можете решить эту проблему, используя различные компоненты WordPress, но вам нужно решить, какое решение вы хотите реализовать.
Давайте сначала узнаем немного о компонентах более высокого порядка и модуле данных WordPress, прежде чем мы рассмотрим, как мы можем выполнять почтовые запросы в нашем блоке.
Модуль основных данных WordPress и компоненты более высокого порядка
При работе с React вам часто потребуется передавать состояние вниз дочерним компонентам или вверх к общему родительскому компоненту, чтобы все остальные дочерние компоненты имели к ним доступ. Решение проблемы централизации состояния приложения — использование Redux. С помощью Redux вы можете создавать хранилища — объекты, содержащие информацию о состоянии и состоянии приложения.
Модуль данных WordPress является центром различных хранилищ и предоставляет функции для управления данными между различными модулями. Он построен на основе Redux, но не путайте его с Redux для WordPress, так как есть довольно много отличий. Вы можете зарегистрировать свои собственные магазины в WordPress или, что более важно, получить доступ к зарегистрированным магазинам WordPress.
Вот обзор доступных магазинов в модуле данных WordPress (вероятно, со временем он изменится). Все магазины WordPress содержатся в модуле Core Data. Например, есть хранилища, содержащие данные редактора (core/editor
), уведомления (core/notices
), данные блоков (core/blocks
), информацию об области просмотра (core/viewport
) и, что не менее важно, само основное хранилище – core
.
Чтобы получить доступ к данным из магазинов, вам нужно будет использовать селекторы. В WordPress есть селектор внутри wp.data
пакета; [select](https://developer.wordpress.org/block-editor/packages/packages-data/#select)()
. Вы также можете манипулировать хранилищами с помощью dispatch
, но это не рассматривается в этой серии руководств. На самом деле вы можете легко попробовать селектор самостоятельно, чтобы увидеть, что доступно в магазинах WordPress.
Пробуем селектор
Откройте редактор Gutenberg в Chrome и откройте инструмент отладки консоли. Введите:
wp.data.select('core')
И нажмите Enter. Вы должны получить объект в качестве ответа со всеми селекторами (функциями), которые вы можете использовать. В качестве примеров вы найдете такие функции, как getMedia
, getTaxonomy
, getAuthors
и так далее. Тот, который мы будем использовать для запросов сообщений, тоже есть, но у него нет интуитивно понятного имени; это называется getEntityRecords
. На данный момент некоторые из этих функций задокументированы, но большинство, к сожалению, нет.
Также попробуйте другие магазины core
, например:
wp.data.select('core/editor').getBlocks()
Это возвращает всю информацию обо всех блоках, которые в настоящее время находятся в вашем сообщении. Вы можете поиграть с этим в отладчике консоли Chrome и попытаться вызвать некоторые функции, чтобы увидеть, что вы получите в ответ. Некоторым требуются параметры, а другим нет.
Чтобы использовать селекторы и доступ к хранилищам, нам нужно использовать их в компонентах более высокого порядка. Компоненты более высокого порядка — это просто шаблон выполнения чего-то в React. Мы передаем компонент функции (или компоненту), которая может добавить некоторые реквизиты, а затем возвращаем новый компонент.
Внутри модуля данных WordPress мы находим [withSelect](https://developer.wordpress.org/block-editor/packages/packages-data/#withSelect)
; компонент более высокого порядка, который можно использовать для внедрения реквизита с помощью зарегистрированных селекторов. Другими словами; внутри withSelect
у нас есть доступ к селектору select()
и мы можем использовать его для выполнения вызовов. Результаты селектора будут реквизитами компонента, которому мы передаем withSelect
. Если вам нужно объединить несколько компонентов более высокого порядка, модуль данных WordPress предлагает эту compose
функцию, но это выходит за рамки этого руководства. Мы будем использовать только один компонент более высокого порядка; withSelect
.
Это было много теории, так что давайте начнем с кода и практических примеров.
Получение сообщений с помощью withSelect, select и getEntityRecords
Подводя итог вышесказанному, нам нужно настроить компонент более высокого порядка withSelect
для нашего блока. Внутри этого мы можем использовать селекторы для доступа к хранилищам WordPress, которые будут реквизитами компонента, которому мы передаем withSelect
. Мы будем использовать core
хранилище и селектор getEntityRecords
для запроса сообщений.
getEntityRecords
К сожалению, на данный момент функция не очень документирована . Но я узнал, что мы можем передать postType
в качестве первого параметра (вид объекта), а затем тип сообщения в качестве второго параметра (например, ‘ post
‘ или ‘ page
‘). Третий параметр является необязательным и может быть объектом с аргументами запроса. Позже мы рассмотрим третий параметр.
Если вы следовали этой серии руководств из предыдущей части, у вас был бы настраиваемый блок, который принимает введенный вручную идентификатор сообщения в текстовом вводе. Блок использует PHP для динамического рендеринга поста во внешнем интерфейсе (и в режиме предварительного просмотра). Давайте удалим необходимость вручную вводить идентификатор сообщения и заменим его чем-то более интуитивным. Как упоминалось ранее, вам нужно решить для себя, как представить список сообщений и как лучше всего позволить пользователю выбрать сообщение. Для простоты мы добавим выбор всех заголовков сообщений на выбор.
КодированиеwithSelect
Давайте начнем кодировать это. Сначала нам нужно деструктурировать то, что нам нужно из пакета данных;
const { withSelect, select } = wp.data;
Затем мы используем функцию withSelect
нашего блока edit
и передаем наш компонент редактирования; FirstBlockEdit
. Внутри withSelect
мы деструктурируем select
как параметр и используем селектор select()
для запроса сообщений с расширением getEntityRecords
. Мы возвращаем объект с одним свойством, которое мы вызываем posts
и которое содержит результат select()
вызова.
С кодом выше наш компонент FirstBlockEdit
теперь будет иметь новую опору; posts
. Все, что мы возвращаем внутри withSelect
компонента более высокого порядка, будет доступно в качестве реквизита для компонента, который мы передаем (в скобках в самом конце).
Обработка постов из селектора
Теперь мы можем зайти в наш компонент FirstBlockEdit
и взглянуть на новый файл props.posts
. Поскольку наш компонент является компонентом, основанным на классах, нам нужно ссылаться на реквизиты с помощью this
. Давайте выполним консольный вход внутри render()
функции в FirstBlockEdit
:
render() {
const { attributes, setAttributes } = this.props;
console.log(this.props.posts);
...
}
Следите за отладчиком консоли. Вы можете заметить, что это будет регистрироваться дважды; сначала null
, а затем некоторое время спустя он регистрирует массив сообщений. Это связано с тем, что запросы к сообщениям выполняются асинхронно. Наш компонент сначала отображается перед ответом, когда время props.posts
равно null
. Как только мы получаем ответ, наш компонент снова перерисовывается с заполненным реквизитом. Вы всегда должны помнить, что в течение этого небольшого промежутка времени в вашем коде не должно быть данных.
Добавление выбора для отображения сообщений
Давайте подготовимся к заполнению выборки возвращенными сообщениями, и для этого мы будем использовать компонент WordPress SelectControl
. Компонент SelectControl
принимает массив вариантов выбора, где каждый вариант представляет собой объект со свойствами value
и label
.
Если вы посмотрите на записанный в консоль (второй) ответ, вы увидите, что мы получаем массив объектов сообщения. Каждое сообщение содержит большую часть информации о сообщении, но для выбора в выборе нас интересует только идентификатор сообщения в качестве значения и заголовок сообщения в качестве метки. Итак, мы пройдемся по posts
реквизиту и заполним переменную массива, которую передадим в SelectControl
. Не забудьте обработать маленький таймфрейм, на котором posts
стоит реквизит null
. В этом случае мы заполним массив выбора одной опцией с меткой «Загрузка…».
Обратите внимание, что нам нужно ссылаться на заголовок сообщения как post.title.rendered
. Можете сами поискать в логе консоли posts
и посмотреть, как структурирована информация для каждого поста.
После этого нам просто нужно добавить SelectControl
везде, где мы этого хотим. Он может быть внутри самого блока (желательно внутри кода для режима редактирования) или внутри Инспектора.
Мы устанавливаем SelectControl
ссылку на атрибут selectedPostId
, который мы определили на предыдущем шаге. Мы устанавливаем сохраненное значение в реквизите value
и обрабатываем его обновление в onChange
реквизите — точно так же, как мы делали это несколько раз раньше. Мы гарантируем, что число сохраняется с помощью использования, parseInt()
потому что selectedPostId
имеет тип number
. И мы передаем сгенерированный массив вариантов в свойство options
.
Вот и все! Если вы следовали коду из предыдущего шага, у вас уже должен быть код, который считывает сохраненный идентификатор сообщения и отображает его!
Конечно, я рекомендую вам реализовать список и выбор сообщений иначе, чем простой выбор. Это не красивое и не удобное решение, особенно для сайтов с большим количеством постов. Говоря о количестве сообщений, вы заметили, что селектор getEntityRecords возвращает максимум 10 последних сообщений? Это поведение getEntityRecords по умолчанию, но мы можем изменить почтовый запрос, передав третий параметр.
Измените запрос для getEntityRecords
Передав объект в качестве третьего параметра в getEntityRecords, мы можем изменить почтовый запрос. Как упоминалось ранее, к сожалению, документация getEntityRecords
отсутствует. Но, прочитав весь Интернет, я собрал список возможных аргументов запроса;
per_page
: Установите число, чтобы ограничить количество сообщений. Установите,-1
чтобы получить максимум 100. По умолчанию10
.exclude
: исключить определенные сообщения из запроса. Установите идентификатор сообщения или массив чисел для нескольких идентификаторов сообщений.parent_exclude
: исключить определенные родительские сообщения. Установите идентификатор сообщения или массив из нескольких идентификаторов сообщений.orderby
: Определите порядок постов. Скорее всего, вы можете использовать те же параметры, что и в orderby WP_Query. Может быть, например, ‘menu_order
‘.order
: Либо'asc'
или ‘desc'
для упорядочения по возрастанию или убыванию.status
: Фильтр по статусу сообщения. Может быть строкой, строкой с несколькими состояниями, разделенными запятой, или массивом строк состояния. Например['publish', 'draft']
, для запроса как опубликованных, так и черновиков сообщений.categories
: фильтрация сообщений по определенным категориям. Укажите идентификатор категории или массив идентификаторов категорий. Я считаю, что это работает только для категорий сообщений, а не для других пользовательских таксономий.tags
: фильтрация сообщений по определенным тегам. Укажите идентификатор тега или массив идентификаторов тегов. Работает только для почтовых тегов, а не для других пользовательских таксономий.search
: добавить поисковый запрос (строка).
Примечание: это не исчерпывающий список, и он также может быть изменен!
Давайте изменим наш запрос. Мы хотим сделать две вещи; сначала мы хотим получить все сообщения, а не только 10 последних. Для этого мы -1
предоставляем per_page
. Во-вторых, мы хотим исключить текущий пост из списка постов, указав идентификатор текущего поста в exclude
. Часто нет смысла показывать ярлык поста или превью самого поста.
Ты можешь подумать; подождите, как мы можем получить текущий идентификатор сообщения? Не забывайте, что мы в компоненте более высокого порядка withSelect
и с помощью select
селектора можем получить доступ ко всем основным хранилищам данных WordPress. Текущий идентификатор записи — это естественная вещь для хранения в одном из основных хранилищ WordPress. Внутри core/editor
находим функцию getCurrentPostId()
.
Давайте изменим withSelect
return примерно так:
Вышеупомянутое изменение говорит само за себя. Мы создаем объект запроса со свойствами per_page
и exclude
передаем его в качестве третьего параметра в getEntityRecords()
. Теперь наш props.posts
внутренний FirstBlockEdit
компонент должен перечислить все сообщения, но исключить текущее сообщение.
Вывод
Этот пост завершает серию руководств по созданию пользовательских блоков Gutenberg. Эта серия предназначена для ознакомления с основами разработки ваших собственных пользовательских блоков, предоставляя вам отправную точку для разработки ваших собственных и более сложных блоков. Обязательно следите за другими уроками, связанными с Гутенбергом, здесь. Возможно, вы найдете учебник, более подробно объясняющий то, что вы хотели сделать сами!