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(