diff --git a/packages/react-dom/src/__tests__/ReactServerRendering-test.js b/packages/react-dom/src/__tests__/ReactServerRendering-test.js index a65fea1c8b110..c2a1e6b3d7f1d 100644 --- a/packages/react-dom/src/__tests__/ReactServerRendering-test.js +++ b/packages/react-dom/src/__tests__/ReactServerRendering-test.js @@ -372,6 +372,28 @@ describe('ReactDOMServer', () => { expect(element.firstChild.focus).not.toHaveBeenCalled(); }); + // Regression test for https://github.com/facebook/react/issues/11726 + it('should not focus on either server or client with autofocus={false} even if there is a markup mismatch', () => { + spyOnDev(console, 'error'); + + var element = document.createElement('div'); + element.innerHTML = ReactDOMServer.renderToString( + , + ); + expect(element.firstChild.autofocus).toBe(false); + + element.firstChild.focus = jest.fn(); + ReactDOM.hydrate(, element); + + expect(element.firstChild.focus).not.toHaveBeenCalled(); + if (__DEV__) { + expect(console.error.calls.count()).toBe(1); + expect(console.error.calls.argsFor(0)[0]).toBe( + 'Warning: Text content did not match. Server: "server" Client: "client"', + ); + } + }); + it('should throw with silly args', () => { expect( ReactDOMServer.renderToString.bind(ReactDOMServer, {x: 123}), diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index b75cabe96ce54..7e9266b0dc9c0 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -704,11 +704,19 @@ const DOMRenderer = ReactFiberReconciler({ newProps: Props, internalInstanceHandle: Object, ): void { - ((domElement: any): - | HTMLButtonElement - | HTMLInputElement - | HTMLSelectElement - | HTMLTextAreaElement).focus(); + // Despite the naming that might imply otherwise, this method only + // fires if there is an `Update` effect scheduled during mounting. + // This happens if `finalizeInitialChildren` returns `true` (which it + // does to implement the `autoFocus` attribute on the client). But + // there are also other cases when this might happen (such as patching + // up text content during hydration mismatch). So we'll check this again. + if (shouldAutoFocusHostComponent(type, newProps)) { + ((domElement: any): + | HTMLButtonElement + | HTMLInputElement + | HTMLSelectElement + | HTMLTextAreaElement).focus(); + } }, commitUpdate(