Вопрос или проблема
Я создал пользовательский блок, который содержит информацию о продукте WooCommerce. Блок в основном представляет собой основной компонент InnerBlocks с шаблоном, который выглядит так:
const createTemplate = (
productName,
productDescription,
productImages,
) => [
[
'core/columns',
{
verticalAlignment: 'center',
className: 'classes',
},
[
[
'core/column',
{
templateLock: false,
className: 'whatever',
},
[
[
'core/column',
{
templateLock: false,
className: 'whatever',
},
[
[
'core/gallery',
{
images: productImages,
},
],
[
'core/paragraph',
{
placeholder: 'Placeholder',
className: 'whatever',
},
],
],
],
[
'core/column',
{
templateLock: 'all',
className:
'd-flex f-column mw-60 w-100 exp-card-left-content-right-col',
},
[
[
'core/heading',
{
placeholder: 'Title',
content: productName || 'Название продукта',
className: 'whatever',
},
],
[
'core/paragraph',
{
placeholder: 'Content',
content: productDescription || 'Описание продукта',
className: 'whatever',
},
],
[
'core/navigation-link',
{
placeholder: 'Добавить ссылку...',
label: 'Смотреть больше',
url: `/product/${selectedProductId}`,
className: 'whatever',
},
],
],
],
],
],
],
],
];
Способ, которым я получаю атрибуты, – это вызов apiFetch:
apiFetch({ path: `/wc/v3/products/${selectedProductId}` })
.then((product) => {
const cleanedDescription = stripHtml(product.description);
// Устанавливаем данные продукта, полученные из API, в атрибуты блока
setAttributes({
productName: product.name,
productDescription: cleanedDescription,
productPrice: product.price,
productImages: product.images.map((img) => ({ url: img.src })),
productInjected: true, // Предотвращает повторные вызовы API
});
// Динамически заменяем содержимое InnerBlocks на полученные данные
wp.data.dispatch('core/block-editor').replaceInnerBlocks(
clientId,
wp.blocks.createBlocksFromInnerBlocksTemplate(
createTemplate(
product.name,
cleanedDescription,
product.price,
product.images.map((img) => ({ url: img.src })),
),
),
);
setLoading(false);
})
.catch((err) => {
setError(err);
setLoading(false);
});
Все работает нормально, за исключением блока core/gallery
. Я предполагаю, что я неправильно формирую объект галереи, но не хватает документации по этому вопросу. Я был бы признателен за любые подсказки.
Похоже, проблема возникает из-за того, что мы не передали идентификатор изображения вместе с URL изображения, поэтому, пожалуйста, попробуйте сделать то же самое и посмотрите.
Вы можете сделать это, заменив данный код
product.images.map((img) => ({ url: img.src }))
на
product.images.map((img) => ({
id: img.id,
url: img.src,
}))
Это изменение обеспечит наличие у каждого объекта изображения
как идентификатора, так и URL, которые ожидает блок core/gallery
.
Ответ или решение
Ваша проблема с использованием блока core/gallery
внутри вашего кастомного блока, скорее всего, связана с неправильным форматом объекта изображения. Блок галереи ожидает, что каждый объект изображения будет содержать не только URL изображения, но и его идентификатор. Для решения этой проблемы нужно изменить формат данных, которые вы передаете в core/gallery
.
Вместо того чтобы использовать следующий код:
product.images.map((img) => ({ url: img.src }))
замените его на:
product.images.map((img) => ({
id: img.id,
url: img.src,
}))
Это изменение гарантирует, что каждый объект изображения включает как id
, так и url
, что является обязательным требованием для блока core/gallery
.
Обновленный фрагмент вашего кода будет выглядеть следующим образом:
apiFetch({ path: `/wc/v3/products/${selectedProductId}` })
.then((product) => {
const cleanedDescription = stripHtml(product.description);
// Установка данных о продукте в атрибуты блока
setAttributes({
productName: product.name,
productDescription: cleanedDescription,
productPrice: product.price,
productImages: product.images.map((img) => ({
id: img.id,
url: img.src,
})),
productInjected: true, // Предотвращает повторные API запросы
});
// Динамическая замена содержимого InnerBlocks с использованием полученных данных
wp.data.dispatch('core/block-editor').replaceInnerBlocks(
clientId,
wp.blocks.createBlocksFromInnerBlocksTemplate(
createTemplate(
product.name,
cleanedDescription,
product.price,
product.images.map((img) => ({
id: img.id,
url: img.src,
})),
),
),
);
setLoading(false);
})
.catch((err) => {
setError(err);
setLoading(false);
});
После внесения этих изменений, блок галереи должен работать корректно, и изображения будут отображаться как предусмотрено. Убедитесь, что зная идентификаторы изображений, вы обеспечиваете правильное взаимодействие с другими возможными блоками и компонентами в вашем проекте. Если вам потребуется более подробная информация или помощь, не стесняйтесь задавать вопросы.