@samitouri / QOS-React-2 / commits / d1c8cdae3b

Ensure updates are applied when diffInCommitPhase is on (#26977)

When we diffInCommitPhase there's no updatePayload, which caused no update to be applied. This is unfortunate because it would've been a lot easier to see this oversight if we didn't have to support both flags. I also carified that updateHostComponent is unnecessary in the new flag. We reuse updateHostComponent for HostSingleton and HostHoistables since it has a somewhat complex path but that means you have to remember when editing updateHostComponent that it's not just used for that tag. Luckily with the new flag, this is actually unnecessary since we just need to mark it for update if any props have changed and then we diff it later.

Sebastian Markbåge committed Jun 19, 2023 at 21:24 UTC d1c8cdae3b20a670ee91b684e8e0ad0c400ae51c
3 files changed +53 -19
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+21
@@ -7084,5 +7084,26 @@ background-color: green;
7084 </html>,
7085 );
7086 });
7087 +
7088 + // @gate enableFloat
7089 + it('can update title tags', async () => {
7090 + const root = ReactDOMClient.createRoot(container);
7091 + await act(() => {
7092 + root.render(<title data-foo="foo">a title</title>);
7093 + });
7094 + await waitForAll([]);
7095 +
7096 + expect(getMeaningfulChildren(document.head)).toEqual(
7097 + <title data-foo="foo">a title</title>,
7098 + );
7099 +
7100 + await act(() => {
7101 + root.render(<title data-foo="bar">another title</title>);
7102 + });
7103 + await waitForAll([]);
7104 + expect(getMeaningfulChildren(document.head)).toEqual(
7105 + <title data-foo="bar">another title</title>,
7106 + );
7107 + });
7108 });
7109 });
packages/react-reconciler/src/ReactFiberCommitWork.js
+1 -1
@@ -2692,7 +2692,7 @@ function commitMutationEffectsOnFiber(
2692 const updatePayload: null | UpdatePayload =
2693 (finishedWork.updateQueue: any);
2694 finishedWork.updateQueue = null;
2695 - if (updatePayload !== null) {
2695 + if (updatePayload !== null || diffInCommitPhase) {
2696 try {
2697 commitUpdate(
2698 finishedWork.stateNode,
packages/react-reconciler/src/ReactFiberCompleteWork.js
+31 -18
@@ -1160,17 +1160,23 @@ function completeWork(
1160 return null;
1161 } else {
1162 // This is a Hoistable Instance
1163 - //
1164 - // We may have props to update on the Hoistable instance. We use the
1165 - // updateHostComponent path becuase it produces the update queue
1166 - // we need for Hoistables.
1167 - updateHostComponent(
1168 - current,
1169 - workInProgress,
1170 - type,
1171 - newProps,
1172 - renderLanes,
1173 - );
1163 + // We may have props to update on the Hoistable instance.
1164 + if (diffInCommitPhase && supportsMutation) {
1165 + const oldProps = current.memoizedProps;
1166 + if (oldProps !== newProps) {
1167 + markUpdate(workInProgress);
1168 + }
1169 + } else {
1170 + // We use the updateHostComponent path becuase it produces
1171 + // the update queue we need for Hoistables.
1172 + updateHostComponent(
1173 + current,
1174 + workInProgress,
1175 + type,
1176 + newProps,
1177 + renderLanes,
1178 + );
1179 + }
1180
1181 // This must come at the very end of the complete phase.
1182 bubbleProperties(workInProgress);
@@ -1192,13 +1198,20 @@ function completeWork(
1198 const rootContainerInstance = getRootHostContainer();
1199 const type = workInProgress.type;
1200 if (current !== null && workInProgress.stateNode != null) {
1195 - updateHostComponent(
1196 - current,
1197 - workInProgress,
1198 - type,
1199 - newProps,
1200 - renderLanes,
1201 - );
1201 + if (diffInCommitPhase && supportsMutation) {
1202 + const oldProps = current.memoizedProps;
1203 + if (oldProps !== newProps) {
1204 + markUpdate(workInProgress);
1205 + }
1206 + } else {
1207 + updateHostComponent(
1208 + current,
1209 + workInProgress,
1210 + type,
1211 + newProps,
1212 + renderLanes,
1213 + );
1214 + }
1215
1216 if (current.ref !== workInProgress.ref) {
1217 markRef(workInProgress);