[reactjs] React.createElement: type is invalid -- expected a string

Trying to get react-router (v4.0.0) and react-hot-loader (3.0.0-beta.6) to play nicely, but getting the following error in the browser console:

Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite
components) but got: undefined. You likely forgot to export your
component from the file it's defined in.

index.js:

import React from 'react';
import ReactDom from 'react-dom';
import routes from './routes.js';
require('jquery');
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import './css/main.css';

const renderApp = (appRoutes) => {
    ReactDom.render(appRoutes, document.getElementById('root'));
};

renderApp( routes() );

routes.js:

import React from 'react';
import { AppContainer } from 'react-hot-loader';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import store from './store/store.js';
import { Provider } from 'react-redux';
import App from './containers/App.jsx';
import Products from './containers/shop/Products.jsx';
import Basket from './containers/shop/Basket.jsx';

const routes = () => (

    <AppContainer>
        <Provider store={store}>
            <Router history={browserHistory}>
                <Route path="/" component={App}>
                    <IndexRoute component={Products} />
                    <Route path="/basket" component={Basket} />
                </Route>
            </Router>
        </Provider>
    </AppContainer>

);

export default routes;

This question is related to reactjs react-router react-hot-loader

The answer is


Most of the time this is due to an incorrect export/import.

Common error:

// File: LeComponent.js
export class LeComponent extends React.Component { ... }

// File: App.js
import LeComponent from './LeComponent';

Possible option:

// File: LeComponent.js 
export default class LeComponent extends React.Component { ... }

// File: App.js
import LeComponent from './LeComponent';

There are a few ways it could be wrong, but that error is because of an import/export mismatch 60% of the time, everytime.

Edit

Typically you should get a stacktrace that indicates an approximate location of where the failure occurs. This generally follows straight after the message you have in your original question.

If it doesn't show, it might be worth investigating why (it might be a build setting that you're missing). Regardless, if it doesn't show, the only course of action is narrowing down where the export/import is failing.

Sadly, the only way to do it, without a stacktrace is to manually remove each module/submodule until you don't get the error anymore, then work your way back up the stack.

Edit 2

Via comments, it was indeed an import issue, specifically importing a module that didn't exist


I was getting this error as well.

I was using:

import ReactDOM from 'react-dom';

Fix was doing this, instead:

import {ReactDOM} from 'react-dom';


This is an error that is some how had to debug. As it has been said many times, improper import/export can cause this error but surprisingly i got this error from a small bug in my react-router-dom authentication setup below is my case:

WRONG SETUP:

const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route
        {...rest}
        render={(props) => (token ? <Component {...props} /> : <Redirect to={{ pathname: "/login" }} />)}
    />
);

CORRECT SETUP:

const PrivateRoute = ({ component: Component, token, ...rest }) => (
    <Route
        {...rest}
        render={(props) => (token ? <Component {...props} /> : <Redirect to={{ pathname: "/login" }} />)}
    />
);

The only difference was I was deconstructing the token in the PrivateRoute component. By the way the token is gotten from localstorage like this const token = localStorage.getItem("authUser"); so if it is not there I know the user is not authenticated. This can also cause that error.


I got the exactly same error, Do this instead:

npm install react-router@next 
react-router-dom@next
npm install --save history

xxxxx.prototype = {
  dxxxx: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

You must add // eslint-disable-line react/forbid-prop-types, then it work!


I was getting this error as well.

I was using:

import BrowserRouter from 'react-router-dom';

Fix was doing this, instead:

import { BrowserRouter } from 'react-router-dom';


In my case, the error occurred when trying to use ContextApi. I have mistakenly used:

const MyContext = () => createContext()

But it should have been defined as:

const MyContext = createContext()

I am posting it here so that future visitors who get stuck on such a silly mistake will get it helpful to avoid hours of headache, coz this is not caused by incorrect import/export.


In my case I forgot to import and export my (new) elements called by the render in the index.js file.


It means your import/export is incorrect.

  • Check newly added import/exports.
  • In my case I was using curly brackets unnecessary. Issue got resolved automatically when I removed these curly brackets.
import { OverlayTrigger } from 'react-bootstrap/OverlayTrigger';

In my case I just had to upgrade from react-router-redux to react-router-redux@next. I'm assuming it must have been some sort of compatibility issue.


You need to be aware of named export and default export. See When should I use curly braces for ES6 import?

In my case, I fixed it by changing from

import Provider from 'react-redux'

to

import { Provider } from 'react-redux'

I just spent 30 minutes trying to solve this BASIC basic issue.

My problem was I was importing react native elements

eg import React, { Text, Image, Component } from 'react';

And trying to use them, which caused me to receive this error.

Once I switch from <Text> to <p> and <Image> to <img> everything worked as expected.


React.Fragment

fixed the issue for me

Error Code:

 return (
            <section className={classes.itemForm}>
             <Card>
             </Card> 
            </section>
      );

Fix

 return (
      <React.Fragment>
        <section className={classes.itemForm}>
         <Card>
         </Card> 
        </section>
      </React.Fragment>
  );

I was getting this error and none of the responses was my case, it might help someone googling:

I was defining a Proptype wrong:

ids: PropTypes.array(PropTypes.string)

It should be:

ids: PropTypes.arrayOf(PropTypes.string)

VSCode and the compile error didnt give me a correct hint.


If you have this error when testing a component, make sure that every child component render correctly when run alone, if one of your child component depend on external resources to render, try to mock it with jest or any other mocking lib:

Exemple:

jest.mock('pathToChildComponent', () => 'mock-child-component')

What missing for me was I was using

import { Router, Route, browserHistory, IndexRoute } from 'react-router';

instead or correct answer should be :

import { BrowserRouter as Router, Route } from 'react-router-dom';

Ofcourse you need to add npm package react-router-dom:

npm install react-router-dom@next --save

Most of the time this indicates an import/export error. But be careful to not only make sure the referenced file in the stack trace is well exported itself, but also that this file is importing other components correctly. In my case the error was like this:

_x000D_
_x000D_
import React from 'react';_x000D_
_x000D_
// Note the .css at the end, this is the cause of the error!_x000D_
import SeeminglyUnimportantComponent from './SeeminglyUnimportantComponent.css';_x000D_
_x000D_
const component = (props) => (            _x000D_
  <div>_x000D_
    <SeeminglyUnimportantComponent />_x000D_
    {/* ... component code here */}_x000D_
  </div>    _x000D_
);_x000D_
_x000D_
export default component;
_x000D_
_x000D_
_x000D_


It's quite simple, really. I got this issue when I started coding React, and the problem is almost always because the import:

import React, { memo } from 'react';

You can use destructuring this because react lib has a property as memo, but you can not destructuring something like this

import { user } from 'assets/images/icons/Profile.svg';

because it's not a object.

Hope it helps!


The application that I was working on, stored the name of react components as a widget configuration in the browser storage. Some of these components got deleted and the app was still trying to render them. By clearing the browser cache, I was able to resolve my issue.


Try this

npm i react-router-dom@next

in your App.js

import { BrowserRouter as Router, Route } from 'react-router-dom'

const Home = () => <h1>Home</h1>

const App = () =>(
  <Router>
    <Route path="/" component={Home} />
  </Router>
)

export default App;

I think the most important thing to realize when troubleshooting this bug is that it manifests when you attempt to instantiate a component that doesn't exist. This component doesn't have to be imported. In my case I was passing components as properties. I forgot to update one of the calls to properly pass the component after some refactoring. Unfortunately, since JS isn't statically typed my bug wasn't caught, and it took some time to figure out what was happening.

To troubleshoot this bug inspect the component before you render it, to make sure that it's the type of component you expect.


EDIT

You are complexifying the process. Just do this :

index.js:

import React from 'react';
import ReactDom from 'react-dom';
import routes from './routes.js';
require('jquery');
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import './css/main.css';

ReactDom.render(<routes />, document.getElementById('root'));

routes.js:

import React from 'react';
import { AppContainer } from 'react-hot-loader';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import store from './store/store.js';
import { Provider } from 'react-redux';
import App from './containers/App.jsx';
import Products from './containers/shop/Products.jsx';
import Basket from './containers/shop/Basket.jsx';

const routes =
    <AppContainer>
        <Provider store={store}>
            <Router history={browserHistory}>
                <Route path="/" component={App}>
                    <IndexRoute component={Products} />
                    <Route path="/basket" component={Basket} />
                </Route>
            </Router>
        </Provider>
    </AppContainer>;

export default routes;

This is not necessary a direct issue related to import/export. In my case, I was rendering a child element inside a parent element and the child element has jsx element / tag which is used but not imported. I imported it and I used it then it fixed the issue. So the problem was in jsx elements which are inside the child element NOT the export of child element itself.


In my case, I have added the same custom component as a prop instead of actual prob

   import AddAddress from '../../components/Manager/AddAddress';
    
    class Add extends React.PureComponent {
      render() {
        const {
          history,
          addressFormData,
          formErrors,
          addressChange,
          addAddress,
          isDefault,
          defaultChange
        } = this.props;
    

Error:

    return (
        <AddAddress
          addressFormData={addressFormData}
          formErrors={formErrors}
          addressChange={addressChange}
          addAddress={AddAddress} // here i have used the Component name as probs in same component itself instead of prob
          isDefault={isDefault}
          defaultChange={defaultChange}
        />
      </SubPage>

Solution:

return (
    <AddAddress
      addressFormData={addressFormData}
      formErrors={formErrors}
      addressChange={addressChange}
      addAddress={addAddress} // removed the component name and give prob name
      isDefault={isDefault}
      defaultChange={defaultChange}
    />
  </SubPage>

// @flow

import React from 'react';
import { styleLocal } from './styles';
import {
  View,
  Text,
  TextInput,
  Image,
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';

export default React.forwardRef((props, ref) => {
const { onSeachClick, onChangeTextSearch , ...otherProps } = props;

  return (
        <View style={styleLocal.sectionStyle}>
        <TouchableOpacity onPress={onSeachClick}>
            <Image                              
                    source={require('../../assets/imgs/search.png')}
                    style={styleLocal.imageStyle} />
                </TouchableOpacity>
            <TextInput
                style={{ flex: 1, fontSize: 18 }}
                placeholder="Search Here"
                underlineColorAndroid="transparent"
                onChangeText={(text) => { onChangeTextSearch(text) }}
            />
        </View>
  );
});
 import IGPSSearch from '../../components/IGPSSearch';
<Search onSeachClick={onSeachClick} onChangeTextSearch= {onChangeTextSearch}> </Search>

For future googlers:

My solution to this problem was to upgrade react and react-dom to their latest versions on NPM. Apparently I was importing a Component that was using the new fragment syntax and it was broken in my older version of React.


I had this problem when I added a css file to the same folder as the component file.

My import statement was:

import MyComponent from '../MyComponent'

which was fine when there was only a single file, MyComponent.jsx. (I saw this format in an example and gave it a try, then forgot I'd done it)

When I added MyComponent.scss to the same folder, the import then failed. Maybe JavaScript loaded the .scss file instead, and so there was no error.

My conclusion: always specify the file extension even if there is only one file, in case you add another one later.


Array of components

A common way to get this error is using an array of components, with a positional index used to select the component to render from the array. I saw a code like this many times:

const checkoutSteps = [Address, Shipment, Payment]

export const Checkout = ({step}) => {

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}

This is not necessary bad code, but if you call it with a wrong index (eg -1, or 3 in this case), the ToRender component will be undefined, throwing the React.createElement: type is invalid... error:

<Checkout step={0} /> // <Address />
<Checkout step={1} /> // <Shipment />
<Checkout step={2} /> // <Payment />
<Checkout step={3} /> // undefined
<Checkout step={-1} /> // undefined

A rational solution

You should protect yourself and your collegues from this hard-to-debug code using a more explicit approach, avoiding magic numbers and using PropTypes:

const checkoutSteps = {
  address: Address,
  shipment Shipment,
  payment: Payment
}

const propTypes = {
  step: PropTypes.oneOf(['address', 'shipment', 'payment']),
}

/* TIP: easier to maintain
const propTypes = {
  step: PropTypes.oneOf(Object.keys(checkoutSteps)),
}
*/

const Checkout = ({step}) => {

  const ToRender = checkoutSteps[step]

  return (
    <ToRender />
  )
}

Checkout.propTypes = propTypes

export default Checkout

And your code will look like this:

// OK
<Checkout step="address" /> // <Address />
<Checkout step="shipment" /> // <Shipment />
<Checkout step="payment" /> // <Payment />

// Errors
<Checkout step="wrongstep" /> // explicit error "step must be one of..."
<Checkout step={3} /> // explicit error (same as above)
<Checkout step={myWrongVar} /> // explicit error (same as above)

Benefits of this approach

  • code is more explicit, you can clearly see what you want to render
  • you don't need to remember the numbers and their hidden meaning (1 is for Address, 2 is for...)
  • errors are explicit too
  • no headache for your peers :)

In simply words, somehow the following is happening:

render() {
    return (
        <MyComponent /> // MyComponent is undefined.
    );
}

It may not necessarily be related with some incorrect import or export:

render() {
    // MyComponent may be undefined here, for example.
    const MyComponent = this.wizards[this.currentStep];

    return (
        <MyComponent />
    );
}

I was missing a React Fragment:


function Bar({ children }) {

  return (
    <div>
     {children}
    </div>
  );
}

function Foo() {
  return (
    <Bar>
      <Baz/>
      <Qux/>
    </Bar>
  );
}

The code above throws the error above. But this fixes it:

<Bar>
  <>
    <Baz/>
    <Qux/>
  </>
</Bar>

Circular dependency is also one of the reasons for this. [in general]


This issue has occurred to me when I had a bad reference in my render/return statement. (point to a non existing class). Also check your return statement code for bad references.


In my case, the order in which you create the component and render, mattered. I was rendering the component before creating it. The best way is to create the child component and then the parent components and then render the parent component. Changing the order fixed the issue for me.


Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

Examples related to react-router

React : difference between <Route exact path="/" /> and <Route path="/" /> You should not use <Link> outside a <Router> React Router Pass Param to Component Detect Route Change with react-router What is the best way to redirect a page using React Router? No restricted globals React-router v4 this.props.history.push(...) not working How to pass params with history.push/Link/Redirect in react-router v4? How to use Redirect in the new react-router-dom of Reactjs How to implement authenticated routes in React Router 4?

Examples related to react-hot-loader

React.createElement: type is invalid -- expected a string