-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A more descriptive createElement warning #7402
Changes from 7 commits
3d1187e
b9dba9e
e782ed5
914f535
c08f81d
037818b
d01e2eb
3662819
6390b8d
056666d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
--- | ||
title: Invalid type for createElement | ||
layout: single | ||
permalink: warnings/create-element-types.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: | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most people will come to this page from the link provided in the warning message. Assuming that is true, I think a more informative message could be shown here without repeating the warning. Instead of:
You could write something like:
|
||
### 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 = () => <div />; | ||
} | ||
|
||
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 <Foo />; // or return <Bar /> | ||
} | ||
} | ||
``` | ||
|
||
### 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 <div /> } | ||
``` | ||
|
||
`App.js` | ||
|
||
```js | ||
import Foo from './Components' // wrong! | ||
// correct: import { Foo } from './Components'; | ||
|
||
class ReactApp extends Component { | ||
render() { | ||
return <Foo />; | ||
} | ||
} | ||
``` | ||
|
||
### Invalid or missing export | ||
|
||
Check that the component is exported properly with the keyword `export`. | ||
|
||
`Components.js` | ||
|
||
```js | ||
const Foo = () => { return <div /> } // Foo needs to be exported | ||
``` | ||
|
||
`App.js` | ||
|
||
```js | ||
import { Foo } from './Components' // Foo is undefined | ||
|
||
class ReactApp extends Component { | ||
render() { | ||
return <Foo />; | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -183,18 +183,46 @@ function validatePropTypes(element) { | |
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() | ||
); | ||
var validType = true; | ||
var warnInvalidType = function(inputValue) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can be expensive to create closures in such a hot path. Can you please hoist that function outside createElement()? |
||
// warning(...) messages need to be string literals. | ||
// If not, we can do a ternary expression to evaluate the need | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is useful, let's keep it. |
||
// for the mistyped import message, and not repeat the message | ||
// twice here. | ||
if (inputValue === undefined) { | ||
warning(false, | ||
'React.createElement: %s is an invalid value for a type. ' + | ||
'It should be a string (for DOM elements), ReactClass or '+ | ||
'React.Component (for composite components). ' + | ||
'Did you mistype an import or forget to export your component?' + | ||
'%s See fb.me/react-warning-create-element for more information.', | ||
inputValue, getDeclarationErrorAddendum() | ||
); | ||
} else { | ||
warning(false, | ||
'React.createElement: %s is an invalid value for a type. ' + | ||
'It should be a string (for DOM elements), ReactClass or ' + | ||
'React.Component (for composite components).' + | ||
'%s See fb.me/react-warning-create-element for more information.', | ||
inputValue, getDeclarationErrorAddendum() | ||
); | ||
} | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let’s remove this newline. |
||
switch (typeof type) { | ||
case 'string': | ||
case 'function': | ||
break; | ||
case 'object': | ||
if (type !== null) { | ||
break; | ||
} | ||
// fallthrough if type is a null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fallthroughs are hard to understand. Can you please rewrite this to avoid it? Maybe replace |
||
default: | ||
// We warn in this case but don't throw. We expect the element creation to | ||
// succeed and there will likely be errors in render. | ||
validType = false; | ||
warnInvalidType(type); | ||
} | ||
|
||
var element = ReactElement.createElement.apply(this, arguments); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s call it
Invalid Element Type Warning
for consistency with other warning’s style. Same for filename, would beinvalid-element-type.md
.