Quando devo usar chaves para a importação do ES6?

766

Parece óbvio, mas fiquei um pouco confuso sobre quando usar chaves para importar um único módulo no ES6. Por exemplo, no projeto React-Native em que estou trabalhando, tenho o seguinte arquivo e seu conteúdo:

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;

No TodoReducer.js, tenho que importá-lo sem chaves:

import initialState from './todoInitialState';

Se eu colocar o initialStatecolchete, recebo o seguinte erro para a seguinte linha de código:

Não é possível ler toda a propriedade de undefined

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

Erros semelhantes também acontecem aos meus componentes com as chaves. Eu queria saber quando eu deveria usar chaves para uma única importação, porque, obviamente, ao importar vários componentes / módulos, você deve colocá-los em chaves, o que eu sei.

Editar:

A publicação do SO aqui não responde à minha pergunta. Em vez disso, pergunto quando devo ou não usar chaves para importar um único módulo ou nunca devo usar chaves para importar um único módulo no ES6 (aparentemente isso não é o caso, como eu vi a importação única com chaves)

TonyGW
fonte

Respostas:

2268

Esta é uma importação padrão :

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

Funciona apenas se Ativer a exportação padrão :

// A.js
export default 42

Nesse caso, não importa qual nome você atribui ao importar:

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

Porque ele sempre vai estar ligado a qualquer que seja o padrão de exportação de A.


Esta é uma importação nomeada chamadaA :

import { A } from './A'

Funciona apenas se Acontiver uma exportação nomeada chamadaA :

export const A = 42

Nesse caso, o nome importa porque você está importando uma coisa específica pelo nome de exportação :

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

Para fazer isso funcionar, adicione uma exportação nomeada correspondente a A:

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

Um módulo pode ter apenas uma exportação padrão , mas quantas exportações nomeadas você desejar (zero, um, dois ou muitos). Você pode importá-los todos juntos:

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

Aqui, importamos a exportação padrão como A, e exportações nomeadas chamadas myAe Something, respectivamente.

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

Também podemos atribuir a eles todos os nomes diferentes ao importar:

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

As exportações padrão tendem a ser usadas para o que você normalmente espera obter do módulo. As exportações nomeadas tendem a ser usadas para utilitários que podem ser úteis, mas nem sempre são necessários. No entanto, cabe a você escolher como exportar coisas: por exemplo, um módulo pode não ter nenhuma exportação padrão.

Este é um ótimo guia para módulos ES, explicando a diferença entre exportações padrão e nomeadas.

Dan Abramov
fonte
4
Existe alguma falha em ter um módulo com exportações individuais export const myA = 43; export const Something = 44;e também com export default { myA, Something }? Então, quando você importa você pode import A from './A';por tudo no módulo, ou import { Something } from './A';então você só tem um pouco do módulo
Michael
12
É bom, mas já existe uma sintaxe para agarrar todas as exportações denominadas em um único objeto: import * as AllTheThings.
Dan Abramov
82
Claramente explicado! Eu gostaria de poder dobrar o voto desta resposta.
Willa
7
que tal isto import 'firebase/storage';ou import 'rxjs/add/operator/map';. O que isso está realmente fazendo?
KYW
9
@kyw: Isso executa o módulo, mas ignora o valor exportado. Útil para efeitos colaterais.
Dan Abramov
84

Eu diria que também há uma notação estrelada para a importpalavra-chave ES6 que vale a pena mencionar.

insira a descrição da imagem aqui

Se você tentar consolar o Mix do log:

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

Você vai ter:

insira a descrição da imagem aqui

Quando devo usar chaves para a importação do ES6?

Os colchetes ficam dourados quando você precisa apenas de componentes específicos do módulo, o que diminui a pegada de empacotadores, como o webpack.

prosti
fonte
4
Sua imagem é a folha de dicas perfeita para esta resposta em particular.
Rodrirokr
1
São import * as Mix from "./A";e import A as Mix from "./A";iguais?
Shafizadeh
40

A resposta de Dan Abramov acima explica sobre as exportações padrão e as exportações nomeadas .

Qual usar?

Citando David Herman : O ECMAScript 6 favorece o estilo de exportação único / padrão e fornece a sintaxe mais agradável para a importação do padrão. A importação de exportações nomeadas pode e até deve ser um pouco menos concisa.

No entanto, no TypeScript, a exportação nomeada é favorecida devido à refatoração. Por exemplo, se você exportar uma classe por padrão e renomeá-la, o nome da classe será alterado apenas nesse arquivo e não nas outras referências, com o nome da classe de exportações com nome renomeado em todas as referências. As exportações nomeadas também são preferidas para utilitários.

Uso geral o que você preferir.

Adicional

A exportação padrão é na verdade uma exportação nomeada com o nome padrão, portanto, a exportação padrão pode ser importada como:

import {default as Sample} from '../Sample.js';
Deepak Sharma
fonte
2
A Additionallinha é uma boa informação. import A from './A'não faz sentido se você estiver exportando sem definir um nome como export default 42.
PGT 24/02
8
Certifique-se de não interpretar mal a citação de David Herman. Isso não significa " É preferível usar sempre exportações simples / padrão no ES6 ", mas sim " Como as exportações únicas são muito comuns, o ES6 suporta melhor os padrões e fornecemos a sintaxe mais agradável ".
Bergi 16/05
15

Se você pensa importapenas como açúcar de sintaxe para módulos, objetos e destruição de nó, acho que é bastante intuitivo.

// 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' // same thing, object functionA and functionB props


// just one prop 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';
Brandon
fonte
9

Para entender o uso de chaves em importdeclarações, primeiro você precisa entender o conceito de destruição introduzido no ES6

  1. Destruição de objetos

    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. Destruição de matriz

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

    Usando correspondência de lista

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

    Usando o operador spread

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

Agora que resolvemos isso, no ES6 você pode exportar vários módulos. Você pode então usar a destruição de objetos, como abaixo

Vamos supor que você tenha um módulo chamado module.js

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

Você gostaria de importar as funções exportadas para index.js;

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

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

Você também pode usar diferentes nomes de variáveis ​​como

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

    pFname('Taylor');
    pLanme('Swift');
theTypan
fonte
Desde que você está mostrando comparações com desestruturação, gostaria de acrescentar a comparação desestruturação equivalente ao seu último comentário: import {printFirstname as pFname, printLastname as pLname} from './module.js'é equivalente a:var foo = {printFirstname: 'p_f_n', printLastname: 'p_l_n'}; var { printFirstname:pFname, printLastname: pLname } = foo; pFname('Taylor'); pLname('Swift');
Adam Moisa
fã de musculação?
Tushar Pandey
@TusharPandey Eu sou um construtor de corpo
theTypan
1
Eu acho que em qualquer explicação sobre importação e quando usar curlys vs não usá-los, se você não menciona a destruição de objetos, você realmente não está dando a melhor explicação. Depois que aprendi sobre a desestruturação, nunca pensei sobre o porquê de usar o encaracolado, isso apenas fez sentido.
Eric Bishard 6/11/19
6

ES6Módulos de resumo :

exportações:

Você tem 2 tipos de exportação:

  1. Exportações nomeadas
  2. Exportações padrão, no máximo 1 por módulo

Sintaxe:

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

Importações:

O tipo de exportação (isto é, exportações nomeadas ou padrão) afeta como importar algo:

  1. Para uma exportação nomeada, precisamos usar chaves e o nome exato como a declaração (ou seja, variável, função ou classe) que foi exportada.
  2. Para uma exportação padrão, podemos escolher o nome.

Sintaxe:

// 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';   

Coisas de interesse:

  1. Use uma lista separada por vírgula entre chaves com o nome correspondente da exportação para a exportação nomeada.
  2. Use um nome de sua escolha sem chaves para uma exportação padrão.

Apelido:

Sempre que você deseja renomear uma importação nomeada, isso é possível por meio de aliases . A sintaxe para isso é a seguinte:

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

Agora importamos, importantData_1 mas o identificador é em myDatavez de importantData_1.

Willem van der Veen
fonte
5

normalmente, quando você exporta uma função, precisa usar o {}

if you have export const x 

você usa import {x} from ''

if you use export default const x 

você precisa usar import X from '' aqui, você pode mudar X para qualquer variável que você quiser

jadlmir
fonte
4

Os chavetas ({}) são usadas para importar ligações nomeadas e o conceito por trás disso é a destruição da atribuição

Uma demonstração simples de como a instrução de importação funciona com um exemplo pode ser encontrada em minha própria resposta a uma pergunta semelhante em Quando usamos '{}' nas importações de javascript?

samuelj90
fonte
1
você definitivamente recebe meu voto para a melhor resposta curta!
Eric Bishard 6/11/19
0

Os chavetas são usadas apenas para importação quando a exportação é nomeada. Se a exportação for o padrão, os chavetas não serão usadas para importação.

Abhishek Kumar
fonte
0

Para uma exportação padrão, não usamos {} quando importamos.

por exemplo

player.js

export default vx;

index.js

import vx from './player';

index.js insira a descrição da imagem aqui

player.js insira a descrição da imagem aqui

Se queremos importar tudo o que exportamos, usamos * insira a descrição da imagem aqui

user260778
fonte