Search code examples
reactjsecmascript-6browserifybabeljs

ReactDOM.render Giving Error For Custom Elements


If I render MyLeftNav inside left-nav.jsx, it works. But when I try to render it inside App.jsx, it builds perfectly fine, but then it gives me following error in the browser console:

Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string...

Build Tools and commands:

babel --presets es2015,react jsx/*.jsx --out-dir jsx/
browserify jsx/jsx/app.js --o js/bundle.js

I have noticed that the bundle.js file which is the output of browserify puts the render statement before importing MyLeftNav. I don't exactly know what is wrong with my import statement. Following are the jsx files:

App.jsx :

import ReactDOM from 'react-dom';
import {MyLeftNav} from './left-nav'

ReactDOM.render(<MyLeftNav />, document.getElementById('left-nav'));

left-nav.jsx :

import React from 'react';
//import ReactDOM from 'react-dom';
import {RaisedButton} from 'material-ui'
import {AppBar} from 'material-ui'
import {LeftNav} from 'material-ui'
//import {NavMenuItem} from './nav-menu'
import {ListItem} from 'material-ui'
import {FontIcon} from 'material-ui'


export default class NavMenuItem extends React.Component {

    constructor(props)
    {
        super(props);
        this.handlePageChange = this.handlePageChange.bind(this);
    }

    handlePageChange()
    {
        $.mobile.changePage("#" + this.props.pageId, {transition:"slide"});
    }

    render()
    {
        return (
            <a href={this.props.pageId} >
                <ListItem primaryText={this.props.name}  leftIcon=
                    {
                        <FontIcon
                          className = "muidocs-icon-action-home"
                        />
                     }
                />
            </a>
        );
    }
}


export default class MyLeftNav extends React.Component {

    constructor(props)
    {
        super(props);
        this.state = {open: false};
        this.handleToggle = this.handleToggle.bind(this);
    }

    handleToggle()
    {
        this.setState({open: !this.state.open});
    }

    render()
    {
        return (
            <div>
                <RaisedButton
                    label="Toggle LeftNav"
                    onClick={this.handleToggle}
                />
                <LeftNav width={200} open={this.state.open}>
                    <AppBar title="AppBar" onClick={this.handleToggle}/>
                    <NavMenuItem name="Home" pageId="#home"/>
                    <NavMenuItem name="Page1" pageId="#page1"/>
                </LeftNav>
            </div>
        );
    }
}

//ReactDOM.render(<MyLeftNav />, document.getElementById('left-nav'));

Solution

  • Just use export, not export default, this will allow you to import the class using curly braces like this {MyLeftNav}

    If you insist on using export default, the modules must be separated, and the class can/must be imported this way:

    import MyLeftNav from './left-nav'

    Also, multiple export defaults in a single module is not allowed.