Skip to content

Custom Views: Prevent re-rendering Block Views and Properties#21186

Merged
nielslyngsoe merged 18 commits intomainfrom
v17/bugfix/block-rerendering
Mar 9, 2026
Merged

Custom Views: Prevent re-rendering Block Views and Properties#21186
nielslyngsoe merged 18 commits intomainfrom
v17/bugfix/block-rerendering

Conversation

@rickbutterfield
Copy link
Copy Markdown
Contributor

Prerequisites

  • I have added steps to test this contribution in the description below

Description

When blocks are sorted in Block List or Block Grid, elements with custom views (blockEditorCustomView extension slot) were being destroyed and recreated, causing unnecessary re-renders and potential state loss.

Root cause:

  1. The repeat directive used an index-based key (`${index}_${contentKey}`), causing Lit to see moved items as different items
  2. The umb-extension-slot immediately destroyed its extensions controller on disconnect, even during DOM moves

Fix:

  1. Changed the repeat key to use only contentKey (stable identifier)
  2. Added deferred destruction to umb-extension-slot - uses setTimeout(0) to defer cleanup, which is cancelled if the element is reconnected (as happens during DOM moves)

How to test:

  1. Create a Block List or Block Grid with a custom view extension
  2. Add console logging or state to verify the custom view component lifecycle
  3. Sort/reorder blocks by dragging
  4. Verify that the custom view is NOT destroyed and recreated (same component instance is preserved)

🤖 Generated with Claude Code

Use stable content key for Lit repeat directive instead of index-based
key. Add deferred destruction to extension-slot to preserve extensions
controller when elements are moved in the DOM during sorting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 17, 2025 13:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes an issue where custom views in Block List and Block Grid editors were unnecessarily destroyed and recreated during drag-and-drop reordering operations, causing performance issues and potential state loss.

Key Changes:

  • Modified repeat directive keys from index-based (${index}_${contentKey}) to stable identifiers (contentKey) in Block List and Block Grid editors
  • Added deferred destruction pattern to umb-extension-slot using setTimeout(0) to handle DOM moves gracefully
  • Ensures extension controllers are preserved during DOM reordering while still being properly cleaned up on permanent removal

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts Implements deferred destruction pattern with timeout management to prevent extension destruction during DOM moves
src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts Changes repeat key from index-based to contentKey-only for stable element identity during reordering
src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts Changes repeat key from index-based to contentKey-only for stable element identity during reordering

rickbutterfield and others added 2 commits December 17, 2025 13:57
Add defensive improvements to the deferred destruction pattern in
umb-extension-slot to address potential edge cases:

- Verify controller exists before skipping re-initialization on reconnect
- Clear any existing pending timeout before setting a new one
- Add unit tests for DOM move, permanent removal, and reconnection scenarios

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

rickbutterfield and others added 2 commits December 17, 2025 14:18
Update test to verify destruction by checking that re-adding the element
after permanent removal creates a new extension instance. Disconnected
Lit elements don't re-render, so checking shadowRoot children after
removal is not a valid assertion.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Replace setTimeout(0) with requestAnimationFrame for the deferred
destruction pattern in umb-extension-slot. This is more semantically
correct for DOM-related operations as it waits for the browser to
complete rendering before firing.

Suggested by @nielslyngsoe in PR review.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@nielslyngsoe nielslyngsoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @rickbutterfield, I have taken over this PR and turned it into something that gives the expected result. The initial version did cause some trouble, but this turned out to be a good cleanup of the cleanup logic.

@nielslyngsoe nielslyngsoe changed the title Block List/Grid: Prevent custom view re-rendering during sorting Custom Views: Prevent re-rendering Block Views and Properties Mar 9, 2026
@nielslyngsoe nielslyngsoe enabled auto-merge (squash) March 9, 2026 16:29
@nielslyngsoe nielslyngsoe merged commit e127bbc into main Mar 9, 2026
26 of 29 checks passed
@nielslyngsoe nielslyngsoe deleted the v17/bugfix/block-rerendering branch March 9, 2026 17:03
nielslyngsoe added a commit that referenced this pull request Mar 10, 2026
* refactor to use Abort Controller instead of requestAnimationFrame

* dismantle currentScope immediately when disconnected

* improve life cycle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants