@@ -108,6 +108,18 @@ function validateContainer(container) {
108108 }
109109}
110110
111+ function getReactRootElementInContainer ( container : any ) {
112+ if ( ! container ) {
113+ return null ;
114+ }
115+
116+ if ( container . nodeType === DOC_NODE_TYPE ) {
117+ return container . documentElement ;
118+ } else {
119+ return container . firstChild ;
120+ }
121+ }
122+
111123function shouldAutoFocusHostComponent (
112124 type : string ,
113125 props : Props ,
@@ -366,9 +378,59 @@ var ReactDOM = {
366378 // Top-level check occurs here instead of inside child reconciler because
367379 // because requirements vary between renderers. E.g. React Art
368380 // allows arrays.
369- invariant (
370- isValidElement ( element ) ,
371- 'render(): Invalid component element.'
381+ if ( ! isValidElement ( element ) ) {
382+ if ( typeof element === 'string' ) {
383+ invariant (
384+ false ,
385+ 'ReactDOM.render(): Invalid component element. Instead of ' +
386+ 'passing a string like \'div\', pass ' +
387+ 'React.createElement(\'div\') or <div />.'
388+ ) ;
389+ } else if ( typeof element === 'function' ) {
390+ invariant (
391+ false ,
392+ 'ReactDOM.render(): Invalid component element. Instead of ' +
393+ 'passing a class like Foo, pass React.createElement(Foo) ' +
394+ 'or <Foo />.'
395+ ) ;
396+ } else if ( element != null && typeof element . props !== 'undefined' ) {
397+ // Check if it quacks like an element
398+ invariant (
399+ false ,
400+ 'ReactDOM.render(): Invalid component element. This may be ' +
401+ 'caused by unintentionally loading two independent copies ' +
402+ 'of React.'
403+ ) ;
404+ } else {
405+ invariant (
406+ false ,
407+ 'ReactDOM.render(): Invalid component element.'
408+ ) ;
409+ }
410+ }
411+ }
412+
413+ if ( __DEV__ ) {
414+ const isRootRenderedBySomeReact = Boolean ( container . _reactRootContainer ) ;
415+ const rootEl = getReactRootElementInContainer ( container ) ;
416+ const hasNonRootReactChild = Boolean ( rootEl && ReactDOMComponentTree . getInstanceFromNode ( rootEl ) ) ;
417+
418+ warning (
419+ ! hasNonRootReactChild ||
420+ isRootRenderedBySomeReact ,
421+ 'render(...): Replacing React-rendered children with a new root ' +
422+ 'component. If you intended to update the children of this node, ' +
423+ 'you should instead have the existing children update their state ' +
424+ 'and render the new components instead of calling ReactDOM.render.'
425+ ) ;
426+
427+ warning (
428+ ! container . tagName || container . tagName . toUpperCase ( ) !== 'BODY' ,
429+ 'render(): Rendering components directly into document.body is ' +
430+ 'discouraged, since its children are often manipulated by third-party ' +
431+ 'scripts and browser extensions. This may lead to subtle ' +
432+ 'reconciliation issues. Try rendering into a container element created ' +
433+ 'for your app.'
372434 ) ;
373435 }
374436
@@ -394,7 +456,18 @@ var ReactDOM = {
394456 'unmountComponentAtNode(...): Target container is not a DOM element.'
395457 ) ;
396458 warnAboutUnstableUse ( ) ;
459+
397460 if ( container . _reactRootContainer ) {
461+ if ( __DEV__ ) {
462+ const rootEl = getReactRootElementInContainer ( container ) ;
463+ const renderedByDifferentReact = rootEl && ! ReactDOMComponentTree . getInstanceFromNode ( rootEl ) ;
464+ warning (
465+ ! renderedByDifferentReact ,
466+ 'unmountComponentAtNode(): The node you\'re attempting to unmount ' +
467+ 'was rendered by another copy of React.'
468+ ) ;
469+ }
470+
398471 // Unmount should not be batched.
399472 return DOMRenderer . unbatchedUpdates ( ( ) => {
400473 return renderSubtreeIntoContainer ( null , null , container , ( ) => {
0 commit comments