diff --git a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
index 9abec3eedd..21131897a5 100644
--- a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
+++ b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
@@ -1002,5 +1002,33 @@ describe('ReactDOMFiber', () => {
container
);
});
+
+ describe('disableNewFiberFeatures', () => {
+ var ReactFeatureFlags = require('ReactFeatureFlags');
+
+ beforeEach(() => {
+ ReactFeatureFlags.disableNewFiberFeatures = true;
+ });
+
+ afterEach(() => {
+ ReactFeatureFlags.disableNewFiberFeatures = false;
+ });
+
+ it('throws if something other than false, null, or an element is returned from render', () => {
+ function Render(props) {
+ return props.children;
+ }
+
+ const message = (
+ 'Warning: Render.render(): A valid React element (or null) must ' +
+ 'be returned. You may have returned undefined, an array or some ' +
+ 'other invalid object.'
+ );
+
+ expect(() => ReactDOM.render(Hi, container)).toThrow(message);
+ expect(() => ReactDOM.render({999}, container)).toThrow(message);
+ expect(() => ReactDOM.render([], container)).toThrow(message);
+ });
+ });
}
});
diff --git a/src/renderers/shared/fiber/ReactChildFiber.js b/src/renderers/shared/fiber/ReactChildFiber.js
index 9302c2ed80..115134e6b9 100644
--- a/src/renderers/shared/fiber/ReactChildFiber.js
+++ b/src/renderers/shared/fiber/ReactChildFiber.js
@@ -36,6 +36,7 @@ var ReactTypeOfWork = require('ReactTypeOfWork');
var emptyObject = require('emptyObject');
var getIteratorFn = require('getIteratorFn');
var invariant = require('invariant');
+var ReactFeatureFlags = require('ReactFeatureFlags');
if (__DEV__) {
var { getCurrentFiberStackAddendum } = require('ReactDebugCurrentFiber');
@@ -1100,6 +1101,39 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// not as a fragment. Nested arrays on the other hand will be treated as
// fragment nodes. Recursion happens at the normal flow.
+ if (ReactFeatureFlags.disableNewFiberFeatures) {
+ // Support only the subset of return types that Stack supports. Treat
+ // everything else as empty, but log a warning.
+ if (typeof newChild === 'object' && newChild !== null) {
+ switch (newChild.$$typeof) {
+ case REACT_ELEMENT_TYPE:
+ return placeSingleChild(reconcileSingleElement(
+ returnFiber,
+ currentFirstChild,
+ newChild,
+ priority
+ ));
+
+ case REACT_PORTAL_TYPE:
+ return placeSingleChild(reconcileSinglePortal(
+ returnFiber,
+ currentFirstChild,
+ newChild,
+ priority
+ ));
+ }
+ }
+
+ const Component = returnFiber.type;
+ invariant(
+ newChild === null || newChild === false,
+ '%s.render(): A valid React element (or null) must be returned. You ' +
+ 'may have returned undefined, an array or some other invalid object.',
+ Component.displayName || Component.name || 'Component'
+ );
+ return deleteRemainingChildren(returnFiber, currentFirstChild);
+ }
+
if (typeof newChild === 'string' || typeof newChild === 'number') {
return placeSingleChild(reconcileSingleTextNode(
returnFiber,