GitHub Commits - Example: React

[Fiber] Don't set .innerHTML when it hasn't changed (#36949)

[Fiber] Don't set .innerHTML when it hasn't changed (#36949)

Fixes #30994. We compared this previously but it regressed in #26501.

@@ -1283,6 +1283,41 @@ describe('ReactDOMComponent', () => {
 1283  1283      expect(container.textContent).toEqual('bonjour');
 1284  1284    });
 1285  1285
 1286 +  it('should not incur unnecessary DOM mutations for equal innerHTML', async () => {
 1287 +    // Regression test for https://github.com/facebook/react/issues/30994.
 1288 +    // Reassigning equal innerHTML destroys and recreates the child nodes,
 1289 +    // which breaks in-progress gestures (e.g. swallows an in-flight click
 1290 +    // when a re-render commits between focus and click) and discards state
 1291 +    // like text selection.
 1292 +    const container = document.createElement('div');
 1293 +    const root = ReactDOMClient.createRoot(container);
 1294 +    await act(() => {
 1295 +      root.render(
 1296 +        <div dangerouslySetInnerHTML={{ __html: 'hi' }} />,
 1297 +      );
 1298 +    });
 1299 +
 1300 +    const node = container.firstChild;
 1301 +    const child = node.firstChild;
 1302 +
 1303 +    // A new object with an equal __html string must not touch the DOM.
 1304 +    await act(() => {
 1305 +      root.render(
 1306 +        <div dangerouslySetInnerHTML={{ __html: 'hi' }} />,
 1307 +      );
 1308 +    });
 1309 +    expect(node.firstChild).toBe(child);
 1310 +
 1311 +    // A different __html string still updates.
 1312 +    await act(() => {
 1313 +      root.render(
 1314 +        <div dangerouslySetInnerHTML={{ __html: 'bye' }} />,
 1315 +      );
 1316 +    });
 1317 +    expect(node.firstChild).not.toBe(child);
 1318 +    expect(node.innerHTML).toEqual('bye');
 1319 +  });
 1320 +
 1286 1321  it('should not incur unnecessary DOM mutations for attributes', async () => {
 1287 1322    const container = document.createElement('div');
 1288 1323    const root = ReactDOMClient.createRoot(container);

0 commit comments

Comments

No comments yet. Start the discussion.