Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object

Expected

I should be able to export my App component file and import it into my index.js.

Results

I get the following error

React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object


My index.js

const React = require('react');
const ReactDOM = require('react-dom');
const App = require('./components/App');
require('./index.css');

ReactDOM.render(
    <App />,
    document.getElementById('app')
);

Then in my components/App.js

const React = require('react');

export default class App extends React.Component {
    render() {
        return (
            <div>
                Hell World! Wasabi Sauce!
            </div>
        );
    }
}

// module.exports = App;

If I uncomment module.exports = App; it will work, but I'm trying to use the export syntax. What is driving me nuts is in another project I am doing the exact same thing here and it's working fine :(

like image 687
Leon Gaban Avatar asked May 14 '17 23:05

Leon Gaban


People also ask

How do you fix element type is invalid expected a string for built in components or a class function for composite components but got undefined?

To solve the error "Element type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got", make sure to import named exports using curly braces and default exports without, and only use functions or classes as components.

What is react createElement?

React. createElement( type, [props], [... children] ) Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span' ), a React component type (a class or a function), or a React fragment type.


2 Answers

The issue you have encountered was caused by mixing two different module systems which differ in the way they are resolved and implemented. CommonJS modules are dynamic and contrary to that ES6 modules are statically analyzable.

Tools like Babel transpile ES6 modules to CommonJS as for now because native support is not ready yet. But, there are subtle differences. By using default export (exports default) the transpiler emitted a CommonJS module with { default } property as there can be named and default export alongside in ES6 module. Following example is perfectly valid ES6 module:

export default class Test1 { }
export class Test2 { }

This would result in { default, Test2 } CommonJS module after transpiling and by using require you get that object as a return value.

In order to import ES6 module's default export in CommonJS you must use require(module).default syntax by the reasons mentioned above.


Debugging React.createElement: type is invalid errors

This error is very common when React tries to render a component when there is an issue with the imported module. Most of the time this is caused by missing export in the module or issues with the path (relative paths are some kind of a joke) and without proper tooling, this may lead to serious hair pulling.

In this case, React couldn't render generic object {__esModule: true, default: function} and just threw an error. When using require there is a possibility to just print out required module to see it's contents which may help to debug the issue.


As a side note, please don't mix CommonJS modules with ES6 modules unless you really need. import/export syntax is reserved for the ES6 modules. When using CommonJS modules, just use module.exports and use require to import them. In the future, most developers will be using standard module format. Until then, be careful when mixing them together.

like image 198
Przemysław Zalewski Avatar answered Sep 27 '22 19:09

Przemysław Zalewski


Very often..

...it is as simple as:

const MyModule = require('./MyModule');

vs

const {MyModule} = require('./MyModule');
like image 21
Mick Avatar answered Sep 27 '22 19:09

Mick