diff --git a/docs/warnings/invalid-element-type.md b/docs/warnings/invalid-element-type.md
new file mode 100644
index 0000000000000..efcda12a098a8
--- /dev/null
+++ b/docs/warnings/invalid-element-type.md
@@ -0,0 +1,91 @@
+---
+title: Invalid Element Type Warning
+layout: single
+permalink: warnings/invalid-element-type.html
+---
+
+You probably came here because your code is trying to create a ReactElement with an invalid type using JSX or the `React.createElement` API. This usually happens when you have an invalid import statement.
+
+`React.createElement` requires an argument of type `string` (e.g. 'div', 'span'), or a `ReactClass`/`React.Component`. It cannot be of type `number`, `boolean`, `undefined` or `null`. See the documentation of this API: [https://facebook.github.io/react/docs/top-level-api.html](https://facebook.github.io/react/docs/top-level-api.html)
+
+The following common examples will trigger this error:
+
+### Invalid types
+
+Ensure that your component is not of the following types: undefined, boolean, number or null.
+
+`Components.js`
+
+```js
+let Foo, Bar;
+
+if (false) {
+ Foo = () =>
;
+}
+
+Bar = React.createElement(42);
+// The following types are invalid, too.
+// Bar = 42;
+// Bar = null;
+// Bar = undefined;
+// Bar = true;
+
+export { Foo, Bar }; // Foo is undefined and Bar is an invalid element.
+```
+
+`App.js`
+
+```js
+import { Foo, Bar } from './Components'
+
+class ReactApp extends Component {
+ render() {
+ return ; // or return
+ }
+}
+```
+
+### Invalid member imports
+
+This happens when attempting to import a member as a default member, or importing a default member as a member.
+
+`Components.js`
+
+```js
+export const Foo = () => { return }
+```
+
+`App.js`
+
+```js
+import Foo from './Components' // wrong!
+// correct: import { Foo } from './Components';
+
+class ReactApp extends Component {
+ render() {
+ return ;
+ }
+}
+```
+
+### Invalid or missing export
+
+Check that the component is exported properly with the keyword `export`.
+
+`Components.js`
+
+```js
+const Foo = () => { return } // Foo needs to be exported
+```
+
+`App.js`
+
+```js
+import { Foo } from './Components' // Foo is undefined
+
+class ReactApp extends Component {
+ render() {
+ return ;
+ }
+}
+```
diff --git a/src/isomorphic/classic/element/ReactElementValidator.js b/src/isomorphic/classic/element/ReactElementValidator.js
index a899654153b48..6e95d23508250 100644
--- a/src/isomorphic/classic/element/ReactElementValidator.js
+++ b/src/isomorphic/classic/element/ReactElementValidator.js
@@ -180,21 +180,37 @@ function validatePropTypes(element) {
}
}
+function warnInvalidType(inputValue) {
+ if (inputValue === undefined) {
+ warning(
+ false,
+ 'React.createElement: undefined is an invalid element type. ' +
+ 'Did you mistype an import or forget to export your component? ' +
+ 'It should be a string (for DOM elements), component ' +
+ 'class or function (for user-defined components).' +
+ '%s See https://fb.me/react-invalid-element-type for more information.',
+ getDeclarationErrorAddendum()
+ );
+ } else {
+ warning(
+ false,
+ 'React.createElement: %s is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component ' +
+ 'class or function (for user-defined components).' +
+ '%s See https://fb.me/react-invalid-element-type for more information.',
+ inputValue,
+ getDeclarationErrorAddendum()
+ );
+ }
+}
+
var ReactElementValidator = {
createElement: function(type, props, children) {
var validType = typeof type === 'string' || typeof type === 'function' ||
(type !== null && typeof type === 'object');
- // We warn in this case but don't throw. We expect the element creation to
- // succeed and there will likely be errors in render.
if (!validType) {
- warning(
- false,
- 'React.createElement: type should not be null, undefined, boolean, or ' +
- 'number. It should be a string (for DOM elements) or a ReactClass ' +
- '(for composite components).%s',
- getDeclarationErrorAddendum()
- );
+ warnInvalidType(type);
}
var element = ReactElement.createElement.apply(this, arguments);
diff --git a/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js b/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js
index d646e1ae98434..92b003bba69a6 100644
--- a/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js
+++ b/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js
@@ -297,24 +297,29 @@ describe('ReactElementValidator', function() {
React.createElement(123);
expect(console.error.calls.count()).toBe(4);
expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: React.createElement: type should not be null, undefined, ' +
- 'boolean, or number. It should be a string (for DOM elements) or a ' +
- 'ReactClass (for composite components).'
+ 'Warning: React.createElement: undefined is an invalid element type. ' +
+ 'Did you mistype an import or forget to export your component? ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). ' +
+ 'See https://fb.me/react-invalid-element-type for more information.'
);
expect(console.error.calls.argsFor(1)[0]).toBe(
- 'Warning: React.createElement: type should not be null, undefined, ' +
- 'boolean, or number. It should be a string (for DOM elements) or a ' +
- 'ReactClass (for composite components).'
+ 'Warning: React.createElement: null is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). ' +
+ 'See https://fb.me/react-invalid-element-type for more information.'
);
expect(console.error.calls.argsFor(2)[0]).toBe(
- 'Warning: React.createElement: type should not be null, undefined, ' +
- 'boolean, or number. It should be a string (for DOM elements) or a ' +
- 'ReactClass (for composite components).'
+ 'Warning: React.createElement: true is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). ' +
+ 'See https://fb.me/react-invalid-element-type for more information.'
);
expect(console.error.calls.argsFor(3)[0]).toBe(
- 'Warning: React.createElement: type should not be null, undefined, ' +
- 'boolean, or number. It should be a string (for DOM elements) or a ' +
- 'ReactClass (for composite components).'
+ 'Warning: React.createElement: 123 is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). ' +
+ 'See https://fb.me/react-invalid-element-type for more information.'
);
React.createElement('div');
expect(console.error.calls.count()).toBe(4);
@@ -336,10 +341,10 @@ describe('ReactElementValidator', function() {
);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: React.createElement: type should not be null, undefined, ' +
- 'boolean, or number. It should be a string (for DOM elements) or a ' +
- 'ReactClass (for composite components). Check the render method of ' +
- '`ParentComp`.'
+ 'Warning: React.createElement: null is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). Check the render method of `ParentComp`. ' +
+ 'See https://fb.me/react-invalid-element-type for more information.'
);
});
@@ -537,9 +542,11 @@ describe('ReactElementValidator', function() {
void {[]};
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: React.createElement: type should not be null, undefined, ' +
- 'boolean, or number. It should be a string (for DOM elements) or a ' +
- 'ReactClass (for composite components).'
+ 'Warning: React.createElement: undefined is an invalid element type. ' +
+ 'Did you mistype an import or forget to export your component? ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). ' +
+ 'See https://fb.me/react-invalid-element-type for more information.'
);
});
diff --git a/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js b/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js
index 4f5417e08413d..18c5eea3d1d66 100644
--- a/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js
+++ b/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js
@@ -219,20 +219,25 @@ describe('ReactJSXElementValidator', function() {
void ;
expect(console.error.calls.count()).toBe(4);
expect(console.error.calls.argsFor(0)[0]).toContain(
- 'type should not be null, undefined, boolean, or number. It should be ' +
- 'a string (for DOM elements) or a ReactClass (for composite components).'
+ 'undefined is an invalid element type. ' +
+ 'Did you mistype an import or forget to export your component? ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). '
);
expect(console.error.calls.argsFor(1)[0]).toContain(
- 'type should not be null, undefined, boolean, or number. It should be ' +
- 'a string (for DOM elements) or a ReactClass (for composite components).'
+ 'null is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). '
);
expect(console.error.calls.argsFor(2)[0]).toContain(
- 'type should not be null, undefined, boolean, or number. It should be ' +
- 'a string (for DOM elements) or a ReactClass (for composite components).'
+ 'true is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). '
);
expect(console.error.calls.argsFor(3)[0]).toContain(
- 'type should not be null, undefined, boolean, or number. It should be ' +
- 'a string (for DOM elements) or a ReactClass (for composite components).'
+ '123 is an invalid element type. ' +
+ 'It should be a string (for DOM elements), component class or function ' +
+ '(for user-defined components). '
);
void ;
expect(console.error.calls.count()).toBe(4);