Как сохранить атрибуты блока, когда выходные данные не изменяются?

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

У меня есть блок с некоторыми настройками, которые влияют только на редактор. Не на вывод. Проблема в том, что когда я изменяю эти настройки, вывод не меняется. Тогда WordPress не обнаруживает изменения и не активирует кнопку “обновить”. В следующий раз, когда я открываю запись, изменения в настройках блока исчезают, потому что они не были сохранены.

Могу ли я вручную активировать кнопку обновления из моего блока?

код

import Edit from "./components/edit/edit"
import PreviewInEditor from "./components/edit/editor-preview";
import BlockSettings from "./components/block-settings/BlockSettings";
import { useBlockProps } from '@wordpress/block-editor';

export default function Editor( props ) {

    function update_settings( settings ) {
        props.setAttributes( { ...props.attributes, settings } );
    }

    if( props.isSelected || props.attributes.price_records.length === 0 ) {
        return ( <div { ...useBlockProps() }>
            <Edit {...props} /> 
            <BlockSettings settings={props.attributes.settings} onChange={update_settings} />
        </div> );
    } else {
        return ( <div { ...useBlockProps() }>
            <PreviewInEditor {...props} />
            <BlockSettings settings={props.attributes.settings} onChange={update_settings} />
        </div>);
    }

}

На самом деле предположение, которое я сделал в вопросе, было ошибочным; Кнопка обновления изменяется не только тогда, когда изменяется вывод функции сохранения. Она также изменяется, когда атрибуты изменяются.

Однако я обнаружил небольшую ошибку, которую на самом деле нельзя увидеть в предоставленном коде. В моем компоненте BlockSettings я использовал useState для обновления настроек внутри компонента. Я также немедленно отправлял settings после их назначения.

Однако useState является асинхронной функцией. Так что фактически я отправлял старое значение. Поскольку я отправил старое значение, атрибуты были идентичны предыдущим значениям. Следовательно, обновление не было запущено.

Исправление оказалось довольно простым. Использование useEffect для реакции на измененное значение сработало для меня.

Так что если кнопка обновления не активируется, перепроверьте, действительно ли вы изменили атрибуты.

Ответ или решение

В условиях разработки пользовательского блока в WordPress встречается проблема, когда изменения в атрибутах блока не приводят к обновлению или сохранению данных, что особенно актуально для настроек, которые не влияют на выходной HTML-код блока. Давайте разберемся, как можно решить эту проблему, применив основные принципы React и JavaScript, используемые в блоках WordPress.

Теория

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

Основная задача заключается в корректном управлении состоянием и обновлением атрибутов таким образом, чтобы WordPress мог обнаруживать изменения даже в тех случаях, когда обновление HTML-кода не требуется. Это особенно касается блоков, где настройки влияют только на редактор, а не на окончательный рендеринг.

Пример

Рассмотрим пример, представленный в вопросе. Мы имеем компонент BlockSettings, который используется для управления настройками внутри блока. В этом компоненте применяется хук useState из React для управления внутренним состоянием настроек. Однако, как вы правильно заметили, useState является асинхронной функцией, и если сразу после вызова setState передать прежнее значение, это может привести к непредвиденным результатам, поскольку состояние обновляется асинхронно. Ваша ошибка заключалась в том, что сразу после вызова setState вы передавали в props.setAttributes старое значение.

Решение

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

Пример использования useEffect для управления изменениями:

import { useState, useEffect } from 'react';

function BlockSettings({ settings, onChange }) {
    const [localSettings, setLocalSettings] = useState(settings);

    // Эффект выполняется каждый раз, когда localSettings изменяется
    useEffect(() => {
        onChange(localSettings);
    }, [localSettings]);

    // Функция для обновления локальных настроек
    const updateLocalSettings = (newSettings) => {
        setLocalSettings(newSettings);
    };

    return (
        <div>
            {/* Компоненты управления для обновления настроек */}
        </div>
    );
}

Применение

Применение данного подхода позволяет избежать передачи состояния до его завершенного обновления. Важно также убедиться, что вы меняете состояние, вызывая setState с новыми значениями, чтобы гарантировать, что отличное значение будет точно передано через props.setAttributes.

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

Эти меры не только оптимизируют процесс разработки, но и обеспечивают стабильность и надежность работы блоков, что особенно важно для поддерживания высокого уровня пользовательского опыта. Надеюсь, это объяснение поможет вам в решении подобных задач и вдохновит на дальнейшее исследование возможностей React и WordPress.

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

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