Skip to content

Commit 50a0d69

Browse files
committed
Protect better against createElement(null/undefined)
This adds a warning to React.createElement in __DEV__ about using null or undefined. This is technically valid since element creation can be considered safe and usable in multiple rendering environments. But rendering in a DOM environment with an element with null/undefined type is not safe.
1 parent 5f4d759 commit 50a0d69

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

src/classic/element/ReactElement.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ ReactElement.createElement = function(type, config, children) {
179179
}
180180

181181
// Resolve default props
182-
if (type.defaultProps) {
182+
if (type && type.defaultProps) {
183183
var defaultProps = type.defaultProps;
184184
for (propName in defaultProps) {
185185
if (typeof props[propName] === 'undefined') {

src/classic/element/ReactElementValidator.js

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var ReactCurrentOwner = require('ReactCurrentOwner');
2424

2525
var getIteratorFn = require('getIteratorFn');
2626
var monitorCodeUse = require('monitorCodeUse');
27+
var warning = require('warning');
2728

2829
/**
2930
* Warn if there's no key explicitly set on dynamic arrays of children or
@@ -239,6 +240,15 @@ function checkPropTypes(componentName, propTypes, props, location) {
239240
var ReactElementValidator = {
240241

241242
createElement: function(type, props, children) {
243+
// We warn in this case but don't throw. We expect the element creation to
244+
// succeed and there will likely be errors in render.
245+
warning(
246+
type != null,
247+
'React.createElement: type should not be null or undefined. It should ' +
248+
'be a string (for DOM elements) or a ReactClass (for composite ' +
249+
'components).'
250+
);
251+
242252
var element = ReactElement.createElement.apply(this, arguments);
243253

244254
// The result can be nullish if a mock or a custom function is used.
@@ -251,22 +261,24 @@ var ReactElementValidator = {
251261
validateChildKeys(arguments[i], type);
252262
}
253263

254-
var name = type.displayName;
255-
if (type.propTypes) {
256-
checkPropTypes(
257-
name,
258-
type.propTypes,
259-
element.props,
260-
ReactPropTypeLocations.prop
261-
);
262-
}
263-
if (type.contextTypes) {
264-
checkPropTypes(
265-
name,
266-
type.contextTypes,
267-
element._context,
268-
ReactPropTypeLocations.context
269-
);
264+
if (type) {
265+
var name = type.displayName;
266+
if (type.propTypes) {
267+
checkPropTypes(
268+
name,
269+
type.propTypes,
270+
element.props,
271+
ReactPropTypeLocations.prop
272+
);
273+
}
274+
if (type.contextTypes) {
275+
checkPropTypes(
276+
name,
277+
type.contextTypes,
278+
element._context,
279+
ReactPropTypeLocations.context
280+
);
281+
}
270282
}
271283
return element;
272284
},

src/classic/element/__tests__/ReactElementValidator-test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,28 @@ describe('ReactElementValidator', function() {
5555
);
5656
});
5757

58+
it('gives a helpful error when passing null or undefined', function() {
59+
spyOn(console, 'warn');
60+
React.createElement(undefined);
61+
React.createElement(null);
62+
expect(console.warn.calls.length).toBe(2);
63+
expect(console.warn.calls[0].args[0]).toBe(
64+
'Warning: React.createElement: type should not be null or undefined. ' +
65+
'It should be a string (for DOM elements) or a ReactClass (for ' +
66+
'composite components).'
67+
);
68+
expect(console.warn.calls[1].args[0]).toBe(
69+
'Warning: React.createElement: type should not be null or undefined. ' +
70+
'It should be a string (for DOM elements) or a ReactClass (for ' +
71+
'composite components).'
72+
);
73+
React.createElement('div');
74+
expect(console.warn.calls.length).toBe(2);
75+
76+
expect(() => React.createElement(undefined)).not.toThrow()
77+
});
78+
79+
5880
it('should check default prop values', function() {
5981
spyOn(console, 'warn');
6082

0 commit comments

Comments
 (0)