ES6: `import * as React` vs `import React`

(Ryan Berdeen) #1

Is there a standard way of importing React into an ES6 module? I’ve noticed two seemingly incompatible styles.

There are a number of React ES6 examples that start

import React from 'react';

class MyComponent extends React.Component { /* ... */ }

This seems weird, as it implies that if React were itself written in ES6, the “react” module would have a default export with a number of properties:

export default {
  Component: ReactComponent
  // ...

rather than a named export:

export {ReactComponent as Component};

To work with a named export, the import would need to look like

import * as React from 'react';
// or
import {Component} from 'react';

Using Babel today, both named and default import statements work because React isn’t an ES6 module. If/when react is written in ES6, one of the two forms of import won’t work unless there are redundant (both default and named) exports.

import * as React” or “import {Component}” makes the most sense to me (and I’ve seen it in, but I can’t find any examples or documentation on the React site.

(Daniel Lo Nigro) #2

For what it’s worth, I’m using

import {Component, PropTypes} from 'react';

when using ES6 syntax.

(Dan Abramov) #3

I just import React, { Component, PropTypes } because JSX wants React to be in scope. Once this is solved at some point, I won’t even need React.

(Michael Chan) #4

Also using import React, { Component, PropTypes } for the same reason @gaearon mentioned. Looking forward to the day I can take React out.

(Sophie Alpert) #5

We haven’t settled on a good story here yet. There was some brief discussion in this PR:

Maybe @sebmarkbage has some more current thoughts on the ES6 module API.

(Vicentedealencar) #6

this is very handy

import { default as Router, Link } from 'react-router';

(Tsingson) #7
import React, { Component, PropTypes } from 'react';


(Nav Garcha) #8

If you’re using webpack you could use the webpack.ProvidePlugin to drop React into scope or even the babel plugin:

(Daniel Friesen) #9

That’s the same as writing:

import Router, { Link } from 'react-router';

(Jack Wilsdon) #10

I believe that import React from 'react' is only possible due to the interop feature of babel-plugin-transform-es2015-modules-commonjs (which is included in the es2015 preset).

Here is the ES6 code I’ll be using for these examples;

import React from "react";


Now if we just use the normal es2015 preset, here’s what is generated;

"use strict";

var _react = require("react");

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }


A default property is defined if one doesn’t exist already, containing all of the exports of React. This is why you can do import React from 'react'.

Here’s the output from running the generated code;

[ 'Children',

But if we disable the interop by setting noInterop on the transform, we get this generated instead;

"use strict";

var _react = require("react");


…oops! There’s no default property on React!


TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at Object.<anonymous> (/tmp/bab/example.out.js:5:20)
    at Module._compile (module.js:573:30)
    at Object.Module._extensions..js (module.js:584:10)
    at Module.load (module.js:507:32)
    at tryModuleLoad (module.js:470:12)
    at Function.Module._load (module.js:462:3)
    at Function.Module.runMain (module.js:609:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:598:3

Disabling noInterop makes Babel assume that everything is an ES6 module, causing it to not create an implicit default property on the import.

The “correct” way of importing React is import * as React from 'react', which gives you this code with interop disabled;

"use strict";

var _react = require("react");