When should I use curly braces for ES6 import?
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.
I would say there is also a starred notation for the import
ES6 keyword worth mentioning.
If you try to console log Mix:
import * as Mix from "./A";
console.log(Mix);
You will get:
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.
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';
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';
Summary ES6 modules:
Exports:
You have two types of exports:
- Named exports
- 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:
- 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.
- 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:
- Use a comma-separated list within curly braces with the matching name of the export for named export.
- 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
.