Вопрос или проблема
У меня есть компонент, который управляет массивом изображений (выбираются с помощью Media Picker через компонент MediaUpload). Изображения хранятся в виде массива. У меня есть функции для добавления, удаления и изменения изображения.
attributes: {
images : {type: 'array', default: []}
}
Это функция удаления. Она определена внутри основной функции редактирования блока. Ей передается индекс в массиве изображения для удаления:
const removeMedia = (idx) => {
let images = structuredClone(attributes.images);
let newImages = [];
for (let i = 0; i < images.length; i++)
{
if (i != idx)
{
newImages.push(images[i]);
}
}
setAttributes({
images: newImages
});
}
Она просто использует атрибуты, которые находятся внутри основной функции редактирования блока. Я думаю, это нормально, потому что весь блок перенаправляется каждый раз, когда вызывается setAttributes. Это правильно? Или мне следует получать атрибуты каким-то другим способом?
Также, мне было бы лучше модифицировать атрибуты?
(Мне не важно, что мой метод удаления элемента из массива немного громоздкий).
.
Ответ или решение
Чтобы ответить на вопрос, как получить атрибуты в блоке Gutenberg и как правильно с ними работать, необходимо подробно рассмотреть структуру и логику работы с Gutenberg-блоками в контексте разработки плагинов и тем для WordPress.
Теория
Gutenberg — это редактор блоков, представленный в WordPress, который позволяет пользователям создавать контент с использованием различных типов блоков. Каждый блок имеет свои атрибуты (properties), которые представляют собой данные, определяющие, как блок отображает и ведет себя. Атрибуты хранятся на уровне компонента React для поддержания функциональности блока.
Для управления состоянием блока (в том числе его атрибутами) используется хук useBlockProps
, предоставленный библиотекой @wordpress/block-editor. Атрибуты определяются в регистрации блока через registerBlockType
, где их типы и значения по умолчанию задаются в объекте attributes
.
В вашем сценарии атрибуты определяются как массив изображений:
attributes: {
images: { type: 'array', default: [] }
}
Функция удаления removeMedia
манипулирует этим массивом, удаляя элемент с заданным индексом, и обновляет состояние блока вызовом setAttributes
, что вызывает повторный рендер блока.
Пример
Вы предоставили функцию для удаления элемента из массива изображений, которая выглядит следующим образом:
const removeMedia = (idx) => {
let images = structuredClone(attributes.images);
let newImages = [];
for (let i = 0; i < images.length; i++) {
if (i != idx) {
newImages.push(images[i]);
}
}
setAttributes({
images: newImages
});
}
Эта функция сначала клонирует текущий массив изображений, затем создает новый массив, исключая индекс для удаления, и обновляет атрибут images
с помощью функции setAttributes
. В вашем коде используется метод structuredClone
, который является современным способом глубокого копирования объектов и массивов в JavaScript.
Применение
-
Оптимизация логики управления атрибутами:
ИспользованиеsetAttributes
является правильным подходом для обновления состояния блока, так как это приводит к автоматическому повторному рендеру блока с обновленным состоянием. Таким образом, ваша логика удаления изображений из массива довольно верна, хотя поиск более оптимального метода избавления от элементов массива, например, использованием методовfilter
илиsplice
, мог бы сделать код более лаконичным и читабельным:const removeMedia = (idx) => { const newImages = attributes.images.filter((_, index) => index !== idx); setAttributes({ images: newImages }); }
-
Изменение атрибутов:
Изменять атрибуты напрямую (например,attributes.images[idx] = ...
) небезопасно, так как это приводит к нарушению принципов React, связанных с неизменностью данных. Вместо этого всегда клонируйте массивы и объекты для изменения, используя...
оператор или функциюmap
. -
Проверка и валидация:
При работе с индексами важно убедиться в корректности их значений, например, добавить проверку, что индекс в пределах массива. -
Закладка на будущее:
При компоновке интерфейсов рекомендуется отделять логику от внешнего интерфейса. Это достигается через использование хуков и хелперов. Если ваш проект расширится, возможно, вы задумаетесь о более сложной системе состояния, как Redux, хотя чаще всего для небольших проектов это избыточно. -
Производительность:
Обновление атрибутов блока каждый раз, когда изменяется один элемент, считается нормальной практикой, но может быть неоптимально в больших системах. В этом случае может быть полезенuseMemo
илиuseCallback
, чтобы избежать ненужного повторного вычисления.
Заключение
Использование setAttributes
— это стандартный и рекомендуемый способ обновления состояния блока в Gutenberg, который обеспечивает корректное обновление вашего UI без непосредственного вмешательства в DOM. Ваш метод удаления вполне адекватен, несмотря на его "громоздкость", но его можно оптимизировать для повышения читаемости и производительности. Очевидно, что глубоко понимая это, вы сможете создавать более модульные и легко поддерживаемые решения в контексте разработки для WordPress.