117

I came across a javascript library that uses the following syntax to import libraries:

import React, { Component, PropTypes } from 'react';

What is the difference between the above method and the following?

import React, Component, PropTypes from 'react';
fox
  • 11,694
  • 20
  • 47
  • 76
  • 4
    The answer is in the [**documentation**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) – adeneo Jun 28 '15 at 05:57
  • 4
    The members to import from the module are enclosed in curlybraces – adeneo Jun 28 '15 at 05:58
  • see also [Javascript (ES6), export const vs export default](http://stackoverflow.com/q/33611812/1048572) – Bergi Jun 07 '16 at 15:24
  • 1
    Ha. If we eliminated all the times one could arguably answer a SO question with "RTFM", even Jon Skeet might have less than six figures. ;^) – ruffin Jan 17 '17 at 12:57

2 Answers2

175
import React, { Component, PropTypes } from 'react';

This says:

Import the default export from 'react' under the name React and import the named exports Component and PropTypes under the same names.

This combines the two common syntaxes which you've probably seen

import React from 'react';
import { Component, PropTypes } from 'react';

The first being used to import and name the default export, the second to import the specified named exports.

As a general rule, most modules will either provide a single, default export, or a list of named exports. It is somewhat less usual for a module to provide both a default export and named exports. However, in the case where there is one feature which is most commonly imported, but also additional sub-features, it is a valid design to export the first as the default, and the remaining ones as named exports. It is in such cases you would use the import syntax you refer to.

The other answers are somewhere between wrong and confusing, possibly because the MDN documents at the time this question was asked were wrong and confusing. MDN showed the example

import name from "module-name";

and said name is the "name of the object that will receive the imported values." But that's misleading and incorrect; first of all, there is only one import value, which will be "received" (why not just say "assigned to", or "used to refer to") name, and the import value in this case is the default export from the module.

Another way of explaining this is to note that the above import is precisely identical to

import { default as name } from "module-name";

and the OP's example is precisely identical to

import { default as React, Component, PropTypes } from 'react';

The MDN documentation went on to show the example

import MyModule, {foo, bar} from "my-module.js";

and claimed that it means

Import an entire module's contents, with some also being explicitly named. This inserts myModule (sic), foo, and bar into the current scope. Note that foo and myModule.foo are the same, as are bar and myModule.bar

What MDN said here, and what other answers claim based on the incorrect MDN documentation, is absolutely wrong, and may be based on an earlier version of the spec. What this actually does is

Import the default module export and some explictly named exports. This inserts MyModule, foo, and bar into the current scope. The export names foo and bar are not accessible via MyModule, which is the default export, not some umbrella covering all exports.

(The default module export is the value exported with the export default syntax, which could also be export {foo as default}.)

The MDN documentation writers may have gotten confused with the following form:

import * as MyModule from 'my-module';

This imports all exports from my-module, and makes them accessible under names such as MyModule.name. The default export is also accessible as MyModule.default, since the default export is really nothing more than another named export with the name default. In this syntax, there is no way to import only a subset of the named exports, although one could import the default export, if there is one, together with all the named exports, with

import myModuleDefault, * as myModule from 'my-module';
36
import React, { Component, PropTypes } from 'react'

This will grab the exported { Component, PropTypes } members from the 'react' module and assign them to Component and PropTypes, respectively. React will be equal to the module's default export.

As noted by torazaburo below, this is the same as

import { default as React, Component, PropTypes } from 'react'

which is shorthand for

import { default as React, Component as Component, PropTypes as PropTypes} from 'react'

Here's another example (link to gist):

// myModule.js
export let a = true
export let b = 42
export let c = 'hello, world!'
// `d` is not exported alone
let d = 'some property only available from default'

// this uses the new object literal notation in es6
// {myVar} expands to { myVar : myVar }, provided myVar exists
// e.g., let test = 22; let o = {test}; `o` is then equal to { test : 22 }
export default { a, b, d }

// example1.js
import something from 'myModule'
console.log(something)
// this yields (note how `c` is not here):
/*
  {
    a : true,
    b : 42,
    d : 'some property only available from default'
  }
*/

// example2.js
import something, { c } from 'myModule'
console.log(something)  // same as above; the `default` export
console.log(c)          // c === 'hello, world!'

// example3.js
import { a, b, d, default as something } from 'myModule'
console.log(a)            // a === true
console.log(b)            // b === 42
console.log(d)            // d === undefined (we didn't export it individually)
console.log(something.d)  // something.d === 'some property...'

I tested the second example with babel:

import test, test3, test2 from './app/lib/queries.js'
console.log(test, test3, test2)

and got a syntax error.

~/code/repo/tutoring $ babel-node test.js
/Users/royhowie/.node/lib/node_modules/babel/node_modules/babel-core/lib/babel/transformation/file/index.js:601
      throw err;
            ^
SyntaxError: /Users/royhowie/code/repo/tutoring/test.js: Unexpected token (1:13)
> 1 | import test, test3, test2 from './app/lib/queries.js'
    |              ^
  2 | 
  3 | console.log(test, test3, test2)
  4 | 

For reference, you can read up on the new import documentation from MDN. However, it is apparently in need of technical review. Dr. Axel Rauschmayer's blog post is a better reference for now.

Community
  • 1
  • 1
royhowie
  • 10,605
  • 14
  • 45
  • 66
  • 1
    *This will grab the { Component, PropTypes } properties from the exports in the 'react' module and assign them to React.* This is incorrect. It assigns the default export to `React`, and the named exports `Component` and `PropTypes` to variables of the same name. Unfortunately, the MDN docs are wrong, as you would find out if you tried it. See http://www.2ality.com/2014/09/es6-modules-final.html. Also, import syntax has absolutely nothing to do with destructuring assignment. –  Jun 28 '15 at 09:25
  • 3
    With regard to your comment about the "new `import` documentation`, reviewing the revision history of that MDN article, the parts you are quoting have not been revised since the page was first written more than a year ago, a period during which the module syntax was changing rapidly. –  Jun 28 '15 at 10:27
  • 1
    @torazaburo I rewrote my answer to be more accurate. – royhowie Jun 28 '15 at 21:20
  • @royhowie Thank you so much for this example!! Literally saved another hour worth of mindlessly browsing around... I just have one question. In `example3.js` why did it print `undefined` for `console.log(d)`? Since you did `export default { a, b, d }` so you did export it in `myModule.js`. –  May 24 '17 at 03:31
  • 2
    @1290 In `myModule.js`, note that `a`, `b`, and `c` were exported individually. This means another file can import them directly with `import { a } from 'myModule'`. On the other hand, `d` is only available via the default export, so another module can access it in two ways: `import thisObjectContainsDefault from 'myModule'` and access it via `thisObjectContainsDefault.d` OR `import { default as wrapperObject }` and `wrapperObject.d`. The benefit of the second approach is that you can also grab items which were individually exported, as can be seen in `example3.js`. – royhowie May 24 '17 at 18:24
  • @royhowie OH I completely missed that. Thank you for taking the time for pointing that out and further explaining. Cleared everything up! :) –  May 24 '17 at 21:54