Warn about undefined return value for memo and forwardRef (#19550)
Brian Vaughn committed
Aug 6, 2020 at 16:12 UTC
a63893ff320c39802e8c37fca84ea023f55230c9
3 files changed
+34
-6
packages/react-dom/src/__tests__/ReactEmptyComponent-test.js
+20
@@ -316,4 +316,24 @@ describe('ReactEmptyComponent', () => {
316
const noscript2 = container.firstChild;
317
expect(noscript2).toBe(null);
318
});
319
+
320
+ it('should warn about React.forwardRef that returns undefined', () => {
321
+ const Empty = () => {};
322
+ const EmptyForwardRef = React.forwardRef(Empty);
323
+
324
+ expect(() => {
325
+ ReactTestUtils.renderIntoDocument(<EmptyForwardRef />);
326
+ }).toThrowError(
327
+ 'ForwardRef(Empty)(...): Nothing was returned from render.',
328
+ );
329
+ });
330
+
331
+ it('should warn about React.memo that returns undefined', () => {
332
+ const Empty = () => {};
333
+ const EmptyMemo = React.memo(Empty);
334
+
335
+ expect(() => {
336
+ ReactTestUtils.renderIntoDocument(<EmptyMemo />);
337
+ }).toThrowError('Empty(...): Nothing was returned from render.');
338
+ });
339
});
packages/react-reconciler/src/ReactChildFiber.new.js
+7
-3
@@ -29,7 +29,9 @@ import {
29
ClassComponent,
30
HostText,
31
HostPortal,
32
+ ForwardRef,
33
Fragment,
34
+ SimpleMemoComponent,
35
Block,
36
} from './ReactWorkTags';
37
import invariant from 'shared/invariant';
@@ -1393,14 +1395,16 @@ function ChildReconciler(shouldTrackSideEffects) {
1395
// Intentionally fall through to the next case, which handles both
1396
// functions and classes
1397
// eslint-disable-next-lined no-fallthrough
1396
- case FunctionComponent: {
1397
- const Component = returnFiber.type;
1398
+ case Block:
1399
+ case FunctionComponent:
1400
+ case ForwardRef:
1401
+ case SimpleMemoComponent: {
1402
invariant(
1403
false,
1404
'%s(...): Nothing was returned from render. This usually means a ' +
1405
'return statement is missing. Or, to render nothing, ' +
1406
'return null.',
1403
- Component.displayName || Component.name || 'Component',
1407
+ getComponentName(returnFiber.type) || 'Component',
1408
);
1409
}
1410
}
packages/react-reconciler/src/ReactChildFiber.old.js
+7
-3
@@ -29,7 +29,9 @@ import {
29
ClassComponent,
30
HostText,
31
HostPortal,
32
+ ForwardRef,
33
Fragment,
34
+ SimpleMemoComponent,
35
Block,
36
} from './ReactWorkTags';
37
import invariant from 'shared/invariant';
@@ -1385,14 +1387,16 @@ function ChildReconciler(shouldTrackSideEffects) {
1387
// Intentionally fall through to the next case, which handles both
1388
// functions and classes
1389
// eslint-disable-next-lined no-fallthrough
1388
- case FunctionComponent: {
1389
- const Component = returnFiber.type;
1390
+ case Block:
1391
+ case FunctionComponent:
1392
+ case ForwardRef:
1393
+ case SimpleMemoComponent: {
1394
invariant(
1395
false,
1396
'%s(...): Nothing was returned from render. This usually means a ' +
1397
'return statement is missing. Or, to render nothing, ' +
1398
'return null.',
1395
- Component.displayName || Component.name || 'Component',
1399
+ getComponentName(returnFiber.type) || 'Component',
1400
);
1401
}
1402
}