905

It seems to be obvious, but I found myself a bit confused about when to use curly braces for importing a single module in ES6. For example, in the React-Native project I am working on, I have the following file and its content:

File initialState.js

var initialState = {
    todo: {
        todos: [
            {id: 1, task: 'Finish Coding', completed: false},
            {id: 2, task: 'Do Laundry', completed: false},
            {id: 2, task: 'Shopping Groceries', completed: false},
        ]
    }
};

export default initialState;

In the TodoReducer.js, I have to import it without curly braces:

import initialState from './todoInitialState';

If I enclose the initialState in curly braces, I get the following error for the following line of code:

Cannot read property todo of undefined

File TodoReducer.js:

export default function todos(state = initialState.todo, action) {
    // ...
}

Similar errors also happen to my components with the curly braces. I was wondering when I should use curly braces for a single import, because obviously, when importing multiple component/modules, you have to enclose them in curly braces, which I know.

The Stack Overflow post at here does not answer my question, instead I am asking when I should or should not use curly braces for importing a single module, or I should never use curly braces for importing a single module in ES6 (this is apparently not the case, as I have seen single import with curly braces required).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
TonyGW
  • 15,511
  • 38
  • 93
  • 165
  • Possible duplicate of [using brackets with javascript import syntax](http://stackoverflow.com/questions/31096597/using-brackets-with-javascript-import-syntax) – nils Apr 22 '16 at 14:04
  • 5
    no, it's different. thanks – TonyGW Apr 22 '16 at 14:10
  • possible duplicate of [ES6 module export options](http://stackoverflow.com/q/25494365/1048572) or [Javascript (ES6), export const vs export default](http://stackoverflow.com/q/33611812/1048572) – Bergi Apr 22 '16 at 14:28
  • 1
    no, it's different. thanks – vikramvi Mar 22 '21 at 10:51
  • How to find out if export is default or named ? e.g. reac-router-dom package's Link ? Let's say I've installed a package and want to import, how will I get to know if to use {} or not – vikramvi Mar 22 '21 at 11:02

11 Answers11

2684

This is a default import:

// B.js
import A from './A'

It only works if A has the default export:

// A.js
export default 42

In this case it doesn’t matter what name you assign to it when importing:

// B.js
import A from './A'
import MyA from './A'
import Something from './A'

Because it will always resolve to whatever is the default export of A.


This is a named import called A:

import { A } from './A'

It only works if A contains a named export called A:

export const A = 42

In this case the name matters because you’re importing a specific thing by its export name:

// B.js
import { A } from './A'
import { myA } from './A' // Doesn't work!
import { Something } from './A' // Doesn't work!

To make these work, you would add a corresponding named export to A:

// A.js
export const A = 42
export const myA = 43
export const Something = 44

A module can only have one default export, but as many named exports as you'd like (zero, one, two, or many). You can import them all together:

// B.js
import A, { myA, Something } from './A'

Here, we import the default export as A, and named exports called myA and Something, respectively.

// A.js
export default 42
export const myA = 43
export const Something = 44

We can also assign them all different names when importing:

// B.js
import X, { myA as myX, Something as XSomething } from './A'

The default exports tend to be used for whatever you normally expect to get from the module. The named exports tend to be used for utilities that might be handy, but aren’t always necessary. However it is up to you to choose how to export things: for example, a module might have no default export at all.

This is a great guide to ES modules, explaining the difference between default and named exports.

Alireza
  • 83,698
  • 19
  • 241
  • 152
Dan Abramov
  • 241,321
  • 75
  • 389
  • 492
  • 5
    Is there any downfall to having a module have individual exports ```export const myA = 43; export const Something = 44;``` as well as a ```export default { myA, Something }``` ? So when you import you can either ```import A from './A';``` for everything in the module, or ```import { Something } from './A';``` so you only get a some of the module – Michael Feb 13 '17 at 18:41
  • 14
    It is fine, but there is already a syntax for grabbing all named exports into a single object: `import * as AllTheThings`. – Dan Abramov Mar 04 '17 at 12:08
  • https://stackoverflow.com/questions/44919566/how-to-add-canvas-in-react-and-also-how-to-draw-rectangle-on-image – Piyush Jul 05 '17 at 10:48
  • 9
    what about this- `import 'firebase/storage';` or `import 'rxjs/add/operator/map';`. What is that actually doing? – kyw Sep 24 '17 at 07:52
  • 11
    @kyw: This executes the module but ignores the exported value. Useful for side effects. – Dan Abramov Feb 12 '18 at 02:33
  • 1
    Note: You can't do `import { A };` when you did `const A = 42; export default A;` This might seem weird, and may break your imports when refactoring from named to default exports (unless you remove the curly braces). I guess it's kinda logical though (sigh..), in the sense that default exports only export a value, not a name. The `export default A` only refers to the value `42` referenced by `A`. – Magne Mar 05 '18 at 20:14
  • 1
    IMHO, in the case of `import { A };` it ought to have assigned it from the default export in case no named export was found.. – Magne Mar 05 '18 at 20:24
  • great answer, except a module can have _zero or_ one default exports (though your examples imply this). – NH. Mar 28 '18 at 15:58
  • @DanAbramov When I use the code you provided, I have this issue : "export 'default' (imported as 'myA') was not found in './mymodule' – HRK44 Aug 08 '18 at 09:47
  • This is a great explanation. Simple, understandable, and to the point. To make this answer truly complete, can you also include an explanation about "import * as Something from 'package'" and how it differs from the other two import styles? – pixelbits Dec 13 '18 at 13:10
  • Hi, I've seen - `export { default } from './MyComponent';` - this kind of syntax being used in places. What does it do differently from simple default export? – saran3h Feb 17 '20 at 07:46
  • I would also like to know what the spaces in curly braces (start and end) do in such cases ? Some have those while some don't in other places. – chxzqw Jul 05 '20 at 15:23
107

I would say there is also a starred notation for the import ES6 keyword worth to mention.

enter image description here

If you try to console log Mix:

import * as Mix from "./A";
console.log(Mix);

You will get:

enter image description here

When should I use curly braces for ES6 import?

The brackets are golden when you need only specific components from the module, which makes smaller footprints for bundlers like webpack.

prosti
  • 27,149
  • 7
  • 127
  • 118
  • 1
    Are `import * as Mix from "./A";` and `import A as Mix from "./A";` the same? – Shafizadeh Feb 11 '20 at 18:48
  • What do you mean by *"starred notation"*? [Wild cards](https://en.wiktionary.org/wiki/wild_card#Noun)? – Peter Mortensen Dec 31 '20 at 03:32
  • @PeterMortensen term star, or starred I believe I used "*" https://www.thefreedictionary.com/starred an asterisk. It was 3 years ago, but I think it's that. – prosti Dec 31 '20 at 12:41
43

Dan Abramov's answer explains about the default exports and named exports.

Which to use?

Quoting David Herman: ECMAScript 6 favors the single/default export style, and gives the sweetest syntax to importing the default. Importing named exports can and even should be slightly less concise.

However, in TypeScript named export is favored because of refactoring. Example, if you default export a class and rename it, the class name will change only in that file and not in the other references, with named exports class name will be renamed in all the references. Named exports is also preferred for utilities.

Overall use whatever you prefer.

Additional

Default export is actually a named export with name default, so default export can be imported as:

import {default as Sample} from '../Sample.js';
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Deepak Sharma
  • 451
  • 4
  • 5
  • 2
    The `Additional` line is good information. `import A from './A'` doesn't make sense if you're exporting without defining a name like `export default 42`. – PGT Feb 24 '17 at 04:53
  • 8
    Please make sure not to misinterpret David Herman's quote. It does not mean "*It is favoured to* always *use single/default exports in ES6*", but rather "*Because single exports are so common, ES6 supports defaults best and we gave them the sweetest syntax*". – Bergi May 16 '17 at 16:42
16

If you think of import as just syntax sugar for Node.js modules, objects, and destructuring, I find it's pretty intuitive.

// bar.js
module = {};

module.exports = {
  functionA: () => {},
  functionB: ()=> {}
};

 // Really all that is is this:
 var module = {
   exports: {
      functionA, functionB
   }
  };

// Then, over in foo.js

// The whole exported object:
var fump = require('./bar.js'); //= { functionA, functionB }
// Or
import fump from './bar' // The same thing - object functionA and functionB properties


// Just one property of the object
var fump = require('./bar.js').functionA;

// Same as this, right?
var fump = { functionA, functionB }.functionA;

// And if we use ES6 destructuring:
var { functionA } =  { functionA, functionB };
// We get same result

// So, in import syntax:
import { functionA } from './bar';
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Brandon
  • 6,354
  • 5
  • 39
  • 64
12

Summary ES6 modules:

Exports:

You have two types of exports:

  1. Named exports
  2. Default exports, a maximum one per module

Syntax:

// Module A
export const importantData_1 = 1;
export const importantData_2 = 2;
export default function foo () {}

Imports:

The type of export (i.e., named or default exports) affects how to import something:

  1. For a named export we have to use curly braces and the exact name as the declaration (i.e. variable, function, or class) which was exported.
  2. For a default export we can choose the name.

Syntax:

// Module B, imports from module A which is located in the same directory

import { importantData_1 , importantData_2  } from './A';  // For our named imports

// Syntax single named import:
// import { importantData_1 }

// For our default export (foo), the name choice is arbitrary
import ourFunction from './A';

Things of interest:

  1. Use a comma-separated list within curly braces with the matching name of the export for named export.
  2. Use a name of your choosing without curly braces for a default export.

Aliases:

Whenever you want to rename a named import this is possible via aliases. The syntax for this is the following:

import { importantData_1 as myData } from './A';

Now we have imported importantData_1, but the identifier is myData instead of importantData_1.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Willem van der Veen
  • 19,609
  • 11
  • 116
  • 113
10

In order to understand the use of curly braces in import statements, first, you have to understand the concept of destructuring introduced in ES6

  1. Object destructuring

    var bodyBuilder = {
      firstname: 'Kai',
      lastname: 'Greene',
      nickname: 'The Predator'
    };
    
    var {firstname, lastname} = bodyBuilder;
    console.log(firstname, lastname); // Kai Greene
    
    firstname = 'Morgan';
    lastname = 'Aste';
    
    console.log(firstname, lastname); // Morgan Aste
    
  2. Array destructuring

    var [firstGame] = ['Gran Turismo', 'Burnout', 'GTA'];
    
    console.log(firstGame); // Gran Turismo
    

    Using list matching

      var [,secondGame] = ['Gran Turismo', 'Burnout', 'GTA'];
      console.log(secondGame); // Burnout
    

    Using the spread operator

    var [firstGame, ...rest] = ['Gran Turismo', 'Burnout', 'GTA'];
    console.log(firstGame);// Gran Turismo
    console.log(rest);// ['Burnout', 'GTA'];
    

Now that we've got that out of our way, in ES6 you can export multiple modules. You can then make use of object destructuring like below.

Let's assume you have a module called module.js

    export const printFirstname(firstname) => console.log(firstname);
    export const printLastname(lastname) => console.log(lastname);

You would like to import the exported functions into index.js;

    import {printFirstname, printLastname} from './module.js'

    printFirstname('Taylor');
    printLastname('Swift');

You can also use different variable names like so

    import {printFirstname as pFname, printLastname as pLname} from './module.js'

    pFname('Taylor');
    pLanme('Swift');
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
theTypan
  • 3,589
  • 3
  • 18
  • 23
  • Since you are showing comparisons to destructuring, I would add the equivalent destructuring comparison to your last comment: `import {printFirstname as pFname, printLastname as pLname} from './module.js'` is equivalent to: ```var foo = {printFirstname: 'p_f_n', printLastname: 'p_l_n'}; var { printFirstname:pFname, printLastname: pLname } = foo; pFname('Taylor'); pLname('Swift'); ``` – Adam Moisa Aug 08 '18 at 01:57
  • bodybuilding fan? – Tushar Pandey Sep 26 '19 at 09:55
  • @TusharPandey I am a body builder – theTypan Sep 26 '19 at 10:38
  • 1
    I think in any explanation of importing and when to use curlys vs not using them , if you are not mentioning object destructing, you really are not giving the best explanation. Once I learned about destructuring I never thought about why iuse the curly anymore, it just intuitively made sense. – Eric Bishard Nov 06 '19 at 19:04
6

Usually when you export a function you need to use the {}.

If you have

export const x

you use

import {x} from ''

If you use

export default const x

you need to use

import x from ''

Here you can change X to whatever variable you want.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
jadlmir
  • 352
  • 1
  • 4
  • 14
4

The curly braces ({}) are used to import named bindings and the concept behind it is destructuring assignment

A simple demonstration of how import statement works with an example can be found in my own answer to a similar question at When do we use '{ }' in javascript imports?.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
samuelj90
  • 6,484
  • 2
  • 35
  • 38
0

The curly braces are used only for import when export is named. If the export is default then curly braces are not used for import.

Abhishek Kumar
  • 367
  • 4
  • 7
0

For a default export we do not use { } when we import.

For example,

File player.js

export default vx;

File index.js

import vx from './player';

File index.js

Enter image description here

File player.js

Enter image description here

If we want to import everything that we export then we use *:

Enter image description here

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
user260778
  • 53
  • 1
  • 4
0
  • If there is any default export in the file, there isn't any need to use the curly braces in the import statement.

  • if there are more than one export in the file then we need to use curly braces in the import file so that which are necessary we can import.

  • You can find the complete difference when to use curly braces and default statement in the below YouTube video (very heavy Indian accent, including rolling on the r's...).

    21. ES6 Modules. Different ways of using import/export, Default syntax in the code. ES6 | ES2015

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123