Способы снижения дублирования кода при создании пользовательских блоков

Вопрос или проблема

Я немного новичок, поэтому, возможно, смотрю на это всё 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;

Теперь вы сможете просто импортировать этот хук в любой из ваших блоков и использовать его, минимизируя повторение кода.

Заключение

Устранение дублирования кода не только упрощает поддержку и тестирование, но и улучшает читабельность вашего проекта. Разделение кода на более мелкие части позволяет повысить его переиспользуемость и делает процесс разработки более удобным. Рассмотрите возможность использования вышеобозначенных принципов, чтобы сделать разработку кастомных блоков более эффективной и менее трудоемкой.

Оцените материал
Добавить комментарий

Капча загружается...