diff --git a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
index 40c9666835..c673423f2b 100644
--- a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
@@ -420,4 +420,27 @@ describe('ReactDOMRoot', () => {
// Still works in the legacy API
ReactDOM.render(
, commentNode);
});
+
+ it('warn if no children passed to hydrateRoot', async () => {
+ expect(() =>
+ ReactDOM.hydrateRoot(container),
+ ).toErrorDev(
+ 'Must provide initial children as second argument to hydrateRoot.',
+ {withoutStack: true},
+ );
+ });
+
+ it('warn if JSX passed to createRoot', async () => {
+ function App() {
+ return 'Child';
+ }
+
+ expect(() => ReactDOM.createRoot(container, )).toErrorDev(
+ 'You passed a JSX element to createRoot. You probably meant to call ' +
+ 'root.render instead',
+ {
+ withoutStack: true,
+ },
+ );
+ });
});
diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js
index 9665cf07f9..46786fcdea 100644
--- a/packages/react-dom/src/client/ReactDOMRoot.js
+++ b/packages/react-dom/src/client/ReactDOMRoot.js
@@ -15,6 +15,7 @@ import type {
} from 'react-reconciler/src/ReactInternalTypes';
import {queueExplicitHydrationTarget} from '../events/ReactDOMEventReplaying';
+import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
export type RootType = {
render(children: ReactNodeList): void,
@@ -174,6 +175,20 @@ export function createRoot(
console.warn(
'hydrate through createRoot is deprecated. Use ReactDOM.hydrateRoot(container, ) instead.',
);
+ } else {
+ if (
+ typeof options === 'object' &&
+ options !== null &&
+ (options: any).$$typeof === REACT_ELEMENT_TYPE
+ ) {
+ console.error(
+ 'You passed a JSX element to createRoot. You probably meant to ' +
+ 'call root.render instead. ' +
+ 'Example usage:\n\n' +
+ ' let root = createRoot(domContainer);\n' +
+ ' root.render();',
+ );
+ }
}
}
if (options.unstable_strictMode === true) {
@@ -237,6 +252,15 @@ export function hydrateRoot(
warnIfReactDOMContainerInDEV(container);
+ if (__DEV__) {
+ if (initialChildren === undefined) {
+ console.error(
+ 'Must provide initial children as second argument to hydrateRoot. ' +
+ 'Example usage: hydrateRoot(domContainer, )',
+ );
+ }
+ }
+
// For now we reuse the whole bag of options since they contain
// the hydration callbacks.
const hydrationCallbacks = options != null ? options : null;