Skip to content

Commit 8628018

Browse files
committed
Disallow Fiber-only render return types when feature flag is on
Except for portals, which we use in some places.
1 parent bf117f8 commit 8628018

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,5 +1002,33 @@ describe('ReactDOMFiber', () => {
10021002
container
10031003
);
10041004
});
1005+
1006+
describe('disableNewFiberFeatures', () => {
1007+
var ReactFeatureFlags = require('ReactFeatureFlags');
1008+
1009+
beforeEach(() => {
1010+
ReactFeatureFlags.disableNewFiberFeatures = true;
1011+
});
1012+
1013+
afterEach(() => {
1014+
ReactFeatureFlags.disableNewFiberFeatures = false;
1015+
});
1016+
1017+
it('throws if something other than false, null, or an element is returned from render', () => {
1018+
function Render(props) {
1019+
return props.children;
1020+
}
1021+
1022+
const message = (
1023+
'Warning: Render.render(): A valid React element (or null) must ' +
1024+
'be returned. You may have returned undefined, an array or some ' +
1025+
'other invalid object.'
1026+
);
1027+
1028+
expect(() => ReactDOM.render(<Render>Hi</Render>, container)).toThrow(message);
1029+
expect(() => ReactDOM.render(<Render>{999}</Render>, container)).toThrow(message);
1030+
expect(() => ReactDOM.render(<Render>[<div />]</Render>, container)).toThrow(message);
1031+
});
1032+
});
10051033
}
10061034
});

src/renderers/shared/fiber/ReactChildFiber.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var ReactTypeOfWork = require('ReactTypeOfWork');
3636
var emptyObject = require('emptyObject');
3737
var getIteratorFn = require('getIteratorFn');
3838
var invariant = require('invariant');
39+
var ReactFeatureFlags = require('ReactFeatureFlags');
3940

4041
if (__DEV__) {
4142
var { getCurrentFiberStackAddendum } = require('ReactDebugCurrentFiber');
@@ -1100,6 +1101,39 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
11001101
// not as a fragment. Nested arrays on the other hand will be treated as
11011102
// fragment nodes. Recursion happens at the normal flow.
11021103

1104+
if (ReactFeatureFlags.disableNewFiberFeatures) {
1105+
// Support only the subset of return types that Stack supports. Treat
1106+
// everything else as empty, but log a warning.
1107+
if (typeof newChild === 'object' && newChild !== null) {
1108+
switch (newChild.$$typeof) {
1109+
case REACT_ELEMENT_TYPE:
1110+
return placeSingleChild(reconcileSingleElement(
1111+
returnFiber,
1112+
currentFirstChild,
1113+
newChild,
1114+
priority
1115+
));
1116+
1117+
case REACT_PORTAL_TYPE:
1118+
return placeSingleChild(reconcileSinglePortal(
1119+
returnFiber,
1120+
currentFirstChild,
1121+
newChild,
1122+
priority
1123+
));
1124+
}
1125+
}
1126+
1127+
const Component = returnFiber.type;
1128+
invariant(
1129+
newChild === null || newChild === false,
1130+
'%s.render(): A valid React element (or null) must be returned. You ' +
1131+
'may have returned undefined, an array or some other invalid object.',
1132+
Component.displayName || Component.name || 'Component'
1133+
);
1134+
return deleteRemainingChildren(returnFiber, currentFirstChild);
1135+
}
1136+
11031137
if (typeof newChild === 'string' || typeof newChild === 'number') {
11041138
return placeSingleChild(reconcileSingleTextNode(
11051139
returnFiber,

0 commit comments

Comments
 (0)