Вопрос или проблема
Я немного новичок, поэтому, возможно, смотрю на это всё backwards – но если это так, то было бы очень ценно, если бы кто-то указал мне правильное направление!
Я создаю несколько пользовательских блоков и испытываю трудности с разбором JSX, React, ES6 импортов и экспортов и т. д. Но я заметил, что немного повторяю себя. Например, многие из моих блоков будут иметь довольно идентичный вариант выбора фонового изображения, и я копирую и вставляю около 30 строк кода из блока в блок для этого.
Мой вопрос: Существует ли способ создать модуль или функцию, которые я мог бы включить вместо того, чтобы повторять этот код снова и снова?
После нескольких часов я только что завершил свою первую попытку, когда столкнулся с каменной стеной, пытаясь понять, как обновить/установить свойства основного блока из другого модуля. Когда новое изображение установлено, ID и URL изображения добавляются в атрибуты блоков, чтобы их можно было использовать позже. Однако, поскольку я обрабатывал изображение и получал ID в отдельном модуле, я не мог сохранить их в атрибутах основного модуля/блока.
Я думал, что возможно вернуть все необходимые значения обратно в основной блок, а затем установить атрибуты там… но это казалось дальнейшим уходом по неправильному пути, поэтому я решил спросить здесь!
Вот код, который я хочу выделить в отдельный модуль/файл/элемент. В данный момент он находится в файле “edit.js” пользовательского блока – часть из него отвечает за получение URL изображения, чтобы его можно было отобразить в редакторе, а остальное – за фактический пользовательский интерфейс в боковой панели настроек/инспекторе
//Получение фоновых изображений для редактирования превью
useEffect(
function () {
if (attributes.backgroundImageMB) {
async function go() {
const response = await apiFetch({
path: `/wp/v2/media/${attributes.backgroundImageMB}`,
method: "GET"
})
setAttributes({ backgroundImageMB_URL: response.media_details.sizes.full.source_url })
}
go()
}
},
[attributes.backgroundImageMB]
)
//Обработка выбора фонового изображения
function backgroundImageMB(x) {
setAttributes( { backgroundImageMB: x.id} )
}
А затем:
<PanelRow>
<div className={"jcc-settings_image-preview"}>
<img src={attributes.backgroundImageMB_URL} />
</div>
<MediaUploadCheck>
<MediaUpload
className={"jcc-settings_image"}
onSelect={backgroundImageMB}
value={attributes.backgroundImageMB}
render={ ({ open }) => {
return <button onClick={open}>Выбрать изображение</button>
}}
/>
</MediaUploadCheck>
</PanelRow>
<PanelRow>
<Button
className={"jcc-settings__rm-bg"}
variant="link"
onClick={ ( e ) => setAttributes( { backgroundImageMB: " ", backgroundImageMB_URL:" " } ) }
>
Удалить фон
</Button>
</PanelRow>
Ответ или решение
Способы уменьшения дублирования кода при создании кастомных блоков
Создание кастомных блоков на основе React и JSX может быть сложной задачей, особенно когда речь идет о дублировании кода. Это распространенная проблема, и, естественно, вы ищете пути оптимизации. Давайте рассмотрим несколько подходов, которые помогут вам устранить дублирование и организовать ваш код более эффективно.
1. Вынесение общих компонентов в отдельные модули
Одним из наиболее эффективных способов удаления дублированного кода является создание переиспользуемых компонентов. Вы можете создать отдельный файл, например BackgroundImageSelector.js
, который будет содержать логику работы с изображениями. В нем будет обрабатываться как выбор изображения, так и его отображение.
Пример:
// BackgroundImageSelector.js
import { useEffect } from 'react';
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
const BackgroundImageSelector = ({ attributes, setAttributes }) => {
useEffect(() => {
if (attributes.backgroundImageMB) {
async function fetchImage() {
const response = await apiFetch({
path: `/wp/v2/media/${attributes.backgroundImageMB}`,
method: "GET"
});
setAttributes({ backgroundImageMB_URL: response.media_details.sizes.full.source_url });
}
fetchImage();
}
}, [attributes.backgroundImageMB]);
const handleImageSelect = (image) => {
setAttributes({ backgroundImageMB: image.id });
};
return (
<>
<div className="jcc-settings_image-preview">
<img src={attributes.backgroundImageMB_URL} alt="" />
</div>
<MediaUploadCheck>
<MediaUpload
className="jcc-settings_image"
onSelect={handleImageSelect}
value={attributes.backgroundImageMB}
render={({ open }) => (
<button onClick={open}>Выбрать изображение</button>
)}
/>
</MediaUploadCheck>
</>
);
};
export default BackgroundImageSelector;
Теперь вы можете использовать этот компонент в любом из ваших блоков без дублирования кода.
2. Использование контекстов
Для управления состоянием и передачи данных между компонентами вы можете воспользоваться React Context API. Это поможет вам избавиться от необходимости передавать пропсы через несколько уровней вложенности. Создайте контекст, который будет хранить атрибуты изображений и функции для их обновления.
Пример:
// ImageContext.js
import React, { createContext, useContext, useState } from 'react';
const ImageContext = createContext();
export const ImageProvider = ({ children }) => {
const [attributes, setAttributes] = useState({ backgroundImageMB: '', backgroundImageMB_URL: '' });
return (
<ImageContext.Provider value={{ attributes, setAttributes }}>
{children}
</ImageContext.Provider>
);
};
export const useImageContext = () => useContext(ImageContext);
Теперь вы можете использовать useImageContext
в любом компоненте для доступа к атрибутам и их обновления.
3. Хук для обработки изображений
Создание кастомного хука – это еще один способ устранить дублирование кода. Вы можете создать хук, который будет содержать всю логику работы с изображениями, включая запрос к API и управление атрибутами.
Пример:
// useBackgroundImage.js
import { useEffect } from 'react';
import apiFetch from '@wordpress/api-fetch';
const useBackgroundImage = (attributes, setAttributes) => {
useEffect(() => {
if (attributes.backgroundImageMB) {
async function fetchImage() {
const response = await apiFetch({
path: `/wp/v2/media/${attributes.backgroundImageMB}`,
method: "GET"
});
setAttributes({ backgroundImageMB_URL: response.media_details.sizes.full.source_url });
}
fetchImage();
}
}, [attributes.backgroundImageMB]);
};
export default useBackgroundImage;
Теперь вы сможете просто импортировать этот хук в любой из ваших блоков и использовать его, минимизируя повторение кода.
Заключение
Устранение дублирования кода не только упрощает поддержку и тестирование, но и улучшает читабельность вашего проекта. Разделение кода на более мелкие части позволяет повысить его переиспользуемость и делает процесс разработки более удобным. Рассмотрите возможность использования вышеобозначенных принципов, чтобы сделать разработку кастомных блоков более эффективной и менее трудоемкой.