diff --git a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js index 40b3a61e8e730..3a893c616e14a 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js @@ -7084,5 +7084,26 @@ background-color: green; , ); }); + + // @gate enableFloat + it('can update title tags', async () => { + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render(a title); + }); + await waitForAll([]); + + expect(getMeaningfulChildren(document.head)).toEqual( + a title, + ); + + await act(() => { + root.render(another title); + }); + await waitForAll([]); + expect(getMeaningfulChildren(document.head)).toEqual( + another title, + ); + }); }); }); diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 89c160df460a2..ef1a97815a653 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -2692,7 +2692,7 @@ function commitMutationEffectsOnFiber( const updatePayload: null | UpdatePayload = (finishedWork.updateQueue: any); finishedWork.updateQueue = null; - if (updatePayload !== null) { + if (updatePayload !== null || diffInCommitPhase) { try { commitUpdate( finishedWork.stateNode, diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index c70c1256a959d..63255e9e6ad78 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -1160,17 +1160,23 @@ function completeWork( return null; } else { // This is a Hoistable Instance - // - // We may have props to update on the Hoistable instance. We use the - // updateHostComponent path becuase it produces the update queue - // we need for Hoistables. - updateHostComponent( - current, - workInProgress, - type, - newProps, - renderLanes, - ); + // We may have props to update on the Hoistable instance. + if (diffInCommitPhase && supportsMutation) { + const oldProps = current.memoizedProps; + if (oldProps !== newProps) { + markUpdate(workInProgress); + } + } else { + // We use the updateHostComponent path becuase it produces + // the update queue we need for Hoistables. + updateHostComponent( + current, + workInProgress, + type, + newProps, + renderLanes, + ); + } // This must come at the very end of the complete phase. bubbleProperties(workInProgress); @@ -1192,13 +1198,20 @@ function completeWork( const rootContainerInstance = getRootHostContainer(); const type = workInProgress.type; if (current !== null && workInProgress.stateNode != null) { - updateHostComponent( - current, - workInProgress, - type, - newProps, - renderLanes, - ); + if (diffInCommitPhase && supportsMutation) { + const oldProps = current.memoizedProps; + if (oldProps !== newProps) { + markUpdate(workInProgress); + } + } else { + updateHostComponent( + current, + workInProgress, + type, + newProps, + renderLanes, + ); + } if (current.ref !== workInProgress.ref) { markRef(workInProgress);