Skip to content

Block Editor: Pass onSuccess callback to mediaUpload in MediaReplaceFlow - #83291

Open
antwonw wants to merge 1 commit into
WordPress:trunkfrom
antwonw:fix/media-replace-flow-on-success
Open

antwonw wants to merge 1 commit into
WordPress:trunkfrom
antwonw:fix/media-replace-flow-on-success

Conversation

@antwonw

@antwonw antwonw commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

Update: Following testing on #83290, @wordpress/upload-media does indeed call onChange?.([attachment]) with the server attachment upon completion, and block attributes (id, href) update properly in state.

However, this PR addresses the visual bug in core/file (#83290) where replacing an embedded PDF in Chrome / Chromium browsers leaves the editor's embedded preview canvas frozen on the previous document.

This PR fixes a bug (#83290) where replacing an existing media item in any block utilizing MediaReplaceFlow (such as core/file, core/image, core/cover, core/audio, core/video) fails to update the block when Client-Side Media Processing is active in WordPress 7.1+.


Why?

Actual Root Cause:
In packages/block-library/src/file/edit.jsx, PDF files with inline previews enabled are rendered using an HTML <object> tag:

<object
    className="wp-block-file__preview"
    data={ href }
    type="application/pdf"
    aria-label={ __( 'Embed of the selected PDF file.' ) }
/>

When a user replaces an existing PDF via Replace → Upload or Replace → Open Media Library:

  1. The block's href attribute updates to the new attachment URL.
  2. Because <object> lacks a React key prop, React performs in-place reconciliation and updates the DOM attribute (element.setAttribute('data', href)).
  3. In Chromium browsers, the native PDF viewer (PDFium) does not listen to dynamic mutations of the data attribute on an existing <object> DOM node. It remains frozen displaying the previous PDF document.
  4. When replacing a document using a file with the same filename (e.g. weekly newsletters or bulletins), the attachment title and fileName text link attribute also remain identical, making the block appear visually unchanged.

With Client-Side Media Processing enabled (window.__clientSideMediaProcessing), getSettings().mediaUpload delegates to @wordpress/upload-media:
1. During processing, upload-media fires onChange with a transient blob: URL representation ({ url: blobUrl }).
2. Blocks receiving this transient URL (e.g. FileEdit, ImageEdit) recognize it via isBlobURL() and return early after caching it in local transient state, waiting for the finalized server attachment before updating persistent block attributes (id, url/href, fileName).
3. When the server-side upload completes, @wordpress/upload-media invokes onSuccess([attachment]).
4. Previously, MediaReplaceFlow only supplied onFileChange and omitted onSuccess. Consequently, the finalized attachment was dropped, the transient blob URL was revoked, and the block fell back to referencing the previous attachment.


How?

Updated Fix:
Add key={ href } to the <object> element in packages/block-library/src/file/edit.jsx:

- <object
+ <object
+     key={ href }
      className="wp-block-file__preview"
      data={ href }
      type="application/pdf"
      aria-label={ __( 'Embed of the selected PDF file.' ) }
  />

When href changes, React unmounts the old <object> DOM node and mounts a new one, cleanly restarting the browser's PDF viewer instance with the new URL.

Initial proposed approach in MediaReplaceFlow (superseded)

In packages/block-editor/src/components/media-replace-flow/index.jsx, we supply an onSuccess callback to mediaUpload that mirrors onFileChange:

getSettings().mediaUpload( {
    allowedTypes,
    filesList: files,
    onFileChange: ( [ media ] ) => {
        selectMedia( media, closeMenu );
    },
    onSuccess: ( [ media ] ) => {
        selectMedia( media, closeMenu );
    },
    onError: onUploadError,
} );

This ensures that:
- For client-side media processing, selectMedia is called with the finalized server attachment upon completion.
- For legacy server-side media processing (@wordpress/media-utils), the existing onFileChange workflow continues to work seamlessly without regressions.


Patch Diff

diff --git a/packages/block-library/src/file/edit.jsx b/packages/block-library/src/file/edit.jsx
index 9ad14ae2cf..f1e39f4cad 100644
--- a/packages/block-library/src/file/edit.jsx
+++ b/packages/block-library/src/file/edit.jsx
@@ -262,6 +262,7 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
 						showHandle={ isSelected }
 					>
 						<object
+							key={ href }
 							className="wp-block-file__preview"
 							data={ href }
 							type="application/pdf"

Unit Test Addition

Initial MediaReplaceFlow unit test (superseded)

Add to packages/block-editor/src/components/media-replace-flow/test/index.js:

it( 'calls selectMedia when mediaUpload completes via onSuccess', async () => {
    // ...
} );

Note: The fix adds a React key prop to the File block's preview <object> element to control DOM reconciliation for browser PDF viewer reload.


Testing Instructions

  1. Using Chrome, open the post editor and add a File block (core/file).
  2. Upload a PDF document (Document A). Verify the inline preview renders.
  3. Select the block, click Replace → Upload, and select a different PDF document (Document B).
  4. Verify: The inline preview immediately updates to display Document B.
  5. Select the block, click Replace → Open Media Library, and choose Document A or another PDF.
  6. Verify: The inline preview updates to display the selected document.

@antwonw
antwonw requested a review from ellatrix as a code owner September 21, 2026 19:09
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: antwonw <antwonw@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions github-actions Bot added the [Package] Block editor /packages/block-editor label Sep 21, 2026
@antwonw
antwonw force-pushed the fix/media-replace-flow-on-success branch from 08a4581 to 1e19e93 Compare September 21, 2026 19:13
@antwonw

antwonw commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

Could a maintainer please add the [Type] Bug labels? Thank you!

@antwonw
antwonw force-pushed the fix/media-replace-flow-on-success branch from 1e19e93 to 5cf81d5 Compare September 21, 2026 19:38
@hbhalodia hbhalodia added the [Type] Bug An existing feature does not function as intended label Sep 22, 2026
@hbhalodia hbhalodia added [Feature] Media Anything that impacts the experience of managing media [Feature] Client Side Media Media processing in the browser with WASM labels Sep 22, 2026
@antwonw
antwonw force-pushed the fix/media-replace-flow-on-success branch from 075beeb to 6a74ff6 Compare September 24, 2026 18:15
@github-actions github-actions Bot added [Package] Block library /packages/block-library and removed [Package] Block editor /packages/block-editor labels Sep 24, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Client Side Media Media processing in the browser with WASM [Feature] Media Anything that impacts the experience of managing media [Package] Block library /packages/block-library [Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants