Skip to content

fix(gutenberg): prevent setAttributes on initial mount to avoid dirtying blocks - #34

Merged
DavidBabinec merged 2 commits into
CoreBunch:mainfrom
dfross:fix/gutenberg-mount-dirty-state
Sep 26, 2026
Merged

DavidBabinec merged 2 commits into
CoreBunch:mainfrom
dfross:fix/gutenberg-mount-dirty-state

Conversation

@dfross

@dfross dfross commented Sep 3, 2026 •

Copy link
Copy Markdown

Fixes #33

Summary

In packages/gutenberg/src/index.tsx, an initial render lifecycle bug causes clean posts, templates, and template parts to be marked as modified ("Review changes") immediately upon opening the WordPress Site Editor or Block Editor.

Problem

The component initializes internal state with empty arrays:

const [classNames, setClassNames] = useState({ active: [], dynamic: [] });

A useEffect hook depends on [classNames] and synchronizes it to Gutenberg via props.setAttributes(...):

useEffect(() => {
    props.setAttributes({
        className: [...classNames.active, ...classNames.dynamic].join(" "),
    });
}, [classNames]);

Because classNames starts empty, this effect fires on initial mount and writes { className: "" } to the block attributes before the saved classes finish loading. Calling setAttributes() during initial render mutates Gutenberg's in-memory entity store, immediately flagging clean pages and template parts with unsaved changes.

Solution

Added an isInitialMount ref guard (useRef(true)):

  • On initial render, the effect detects the mount phase, sets isInitialMount.current = false, and returns without calling setAttributes().
  • Subsequent user interactions (hovering over classes for dynamic preview, toggling classes) continue to function normally.
  • Prevents Gutenberg blocks from being wiped with className: "" on initial load.

Skipping only the first effect run still dirtied blocks whose saved
className had extra whitespace, and every block under StrictMode, where
the effect runs twice. The panel now starts from the saved classes and
only writes when the className actually differs. Rebuilds the bundled
editor script.
@DavidBabinec
DavidBabinec merged commit 25542af into CoreBunch:main Sep 26, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Redundant mount useEffect calls setAttributes and dirties blocks on initial load

2 participants