Juan Carlos Farah
Juan Carlos Farah

Reputation: 3879

Uncaught TypeError rendering <Router> using React Router in ES6: type.toUpperCase is not a function

I recently upgraded to React v. 0.14.0, ReactDOM v. 0.14.0 and React Router v. 1.0.0-rc3 and I'm struggling with the following error. I've read and tried solutions in this and this post, but I cannot get it to work for my code, which uses ES6.

The error occurs in my client-side app.js when calling the ReactDOM.render method.

import React from 'react';
import ReactDOM from 'react-dom';
import Router from 'react-router';
import routes from './routes';
import createBrowserHistory from 'history/lib/createBrowserHistory';

let app = document.getElementById('app');
let history = createBrowserHistory();
ReactDOM.render(<Router routes={routes} history={history} />, app);

And this is from my routes.js.

import React from 'react';
import {Route, IndexRoute} from 'react-router';
import App from './components/App';
import Home from './components/Home';

export default (
    <Route path="/" component={App}>
        <IndexRoute component={Home} />
    </Route>
);

And just for completeness, this is my server-side rendering middleware, which seems to be working fine.

app.use(function(req, res) {
    match(
        { routes, location: req.path },
        (error, redirectLocation, renderProps) => {
            if (error) {
                res.send(500, error.message)
            } else if (redirectLocation) {
                res.redirect(302,
                             redirectLocation.pathname +
                             redirectLocation.search)
            } else if (renderProps) {
                let html = renderToString(<RoutingContext {...renderProps} />);
                let page = swig.renderFile('views/index.html', { html: html });
                res.status(200).send(page);
            } else {
                res.status(404).send('Not found');
            }
    });
});

When I inspect the client-side logs I see the following warning before the error:

Warning: React.createElement: type should not be null or undefined. It should be a string (for DOM elements) or a ReactClass (for composite components).

And the actual error happens in the third line of the autoGenerateWrapperClass function in the ReactDefaultInjection module.

function autoGenerateWrapperClass(type) {
  return ReactClass.createClass({
    tagName: type.toUpperCase(),
    render: function() {
      return new ReactElement(
        type,
        null,
        null,
        null,
        null,
        this.props
      );
    }
  });
}

Upvotes: 2

Views: 730

Answers (2)

Juan Carlos Farah
Juan Carlos Farah

Reputation: 3879

Thanks to a response I got to this issue I opened in the react-router repo, I was able to solve the problem. For some reason, I was loading two copies of React, one in version 0.13.3 and another in version 0.14.0. It seems that Browserify was causing this as I was able to resolve this by adding browserify-resolutions to my build process. So my gulp-file ended up including the following (adding the .plugin(resolutions, '*') line to two tasks.

// Compile third-party dependencies separately for faster performance.
gulp.task('browserify-vendor', function() {
    return browserify()
        .require(dependencies)
        .plugin(resolutions, '*')
        .bundle()
        .pipe(source('vendor.bundle.js'))
        .pipe(gulpif(production, streamify(uglify({ mangle: false }))))
        .pipe(gulp.dest('public/js'));
});

// Compile only project files, excluding all third-party dependencies.
gulp.task('browserify', ['browserify-vendor'], function() {
    return browserify('src/app.js')
        .external(dependencies)
        .plugin(resolutions, '*')
        .transform(babelify)
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(gulpif(production, streamify(uglify({ mangle: false }))))
        .pipe(gulp.dest('public/js'));
});

Once I added this, the issue in question went away.

Upvotes: 0

Chris Shepherd
Chris Shepherd

Reputation: 1496

In my experience this usually happens when one of my Components is actually null or undefined.

Upvotes: 1

Related Questions