¿Cuándo debo usar llaves para importar ES6?

767

Parece obvio, pero me encontré un poco confundido acerca de cuándo usar llaves para importar un solo módulo en ES6. Por ejemplo, en el proyecto React-Native en el que estoy trabajando, tengo el siguiente archivo y su contenido:

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;

En TodoReducer.js, tengo que importarlo sin llaves:

import initialState from './todoInitialState';

Si adjunto las initialStatellaves, aparece el siguiente error para la siguiente línea de código:

No se puede leer la propiedad todo de indefinido

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

Errores similares también le ocurren a mis componentes con llaves. Me preguntaba cuándo debería usar llaves para una sola importación, porque obviamente, al importar múltiples componentes / módulos, debe encerrarlos en llaves, lo que sé.

Editar:

La publicación SO aquí no responde a mi pregunta, en cambio estoy preguntando cuándo debería o no usar llaves para importar un solo módulo, o nunca debería usar llaves para importar un solo módulo en ES6 (aparentemente este no es el caso, como he visto importación única con llaves necesarias)

TonyGW
fuente

Respuestas:

2273

Esta es una importación predeterminada :

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

Solo funciona si Atiene la exportación predeterminada :

// A.js
export default 42

En este caso, no importa qué nombre le asignes al importar:

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

Porque siempre se resolverá a lo que sea la exportación predeterminada de A.


Esta es una importación con nombre llamadaA :

import { A } from './A'

Solo funciona si Acontiene una exportación con nombre llamadaA :

export const A = 42

En este caso, el nombre importa porque está importando algo específico por su nombre de exportación :

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

Para que esto funcione, debe agregar una exportación con nombre correspondiente a A:

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

Un módulo solo puede tener una exportación predeterminada , pero tantas exportaciones con nombre como desee (cero, uno, dos o muchos). Puedes importarlos todos juntos:

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

Aquí, importamos la exportación predeterminada como A, y las exportaciones con nombre llamadas myAy Something, respectivamente.

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

También podemos asignarles nombres diferentes al importar:

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

Las exportaciones predeterminadas tienden a usarse para lo que normalmente espera obtener del módulo. Las exportaciones nombradas tienden a usarse para utilidades que pueden ser útiles, pero que no siempre son necesarias. Sin embargo, depende de usted elegir cómo exportar las cosas: por ejemplo, un módulo podría no tener una exportación predeterminada.

Esta es una excelente guía para los módulos ES, que explica la diferencia entre exportaciones predeterminadas y con nombre.

Dan Abramov
fuente
44
¿Hay alguna desventaja en que un módulo tenga exportaciones individuales export const myA = 43; export const Something = 44;, así como a export default { myA, Something }? Entonces, cuando importa puede hacerlo import A from './A';para todo en el módulo, o import { Something } from './A';solo obtiene un poco del módulo
Michael
12
Está bien, pero ya hay una sintaxis para agarrar todas las exportaciones nombrados en un único objeto: import * as AllTheThings.
Dan Abramov
82
Explicado claramente! Desearía poder duplicar el voto de esta respuesta.
Willa
77
¿Qué pasa con esto import 'firebase/storage';o import 'rxjs/add/operator/map';? ¿Qué está haciendo eso realmente?
kyw
99
@kyw: Esto ejecuta el módulo pero ignora el valor exportado. Útil para los efectos secundarios.
Dan Abramov
84

Diría que también hay una notación destacada para la importpalabra clave ES6 que vale la pena mencionar.

ingrese la descripción de la imagen aquí

Si intenta consolar el registro de Mix:

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

Conseguirás:

ingrese la descripción de la imagen aquí

¿Cuándo debo usar llaves para importar ES6?

Los corchetes son dorados cuando solo necesita componentes específicos del módulo, lo que crea huellas más pequeñas para los paquetes como webpack.

prosti
fuente
44
Su imagen es la hoja de trucos perfecta para esta respuesta en particular.
Rodrirokr
1
¿Son import * as Mix from "./A";y import A as Mix from "./A";lo mismo?
Shafizadeh
40

La respuesta anterior de Dan Abramov explica las exportaciones predeterminadas y las exportaciones con nombre .

¿Cuál usar?

Citando a David Herman : ECMAScript 6 favorece el estilo de exportación único / predeterminado y brinda la sintaxis más dulce para importar el valor predeterminado. Importar exportaciones con nombre puede e incluso debería ser un poco menos conciso.

Sin embargo, en TypeScript, la exportación con nombre se ve favorecida por la refactorización. Ejemplo, si exporta por defecto una clase y le cambia el nombre, el nombre de la clase cambiará solo en ese archivo y no en las otras referencias, con el nombre de clase de exportaciones con nombre se cambiará el nombre en todas las referencias. Las exportaciones con nombre también se prefieren para los servicios públicos.

En general, use lo que prefiera.

Adicional

La exportación predeterminada es en realidad una exportación con nombre con nombre predeterminado, por lo que la exportación predeterminada se puede importar como:

import {default as Sample} from '../Sample.js';
Deepak Sharma
fuente
2
La Additionallínea es buena información. import A from './A'no tiene sentido si está exportando sin definir un nombre como export default 42.
PGT
8
Asegúrese de no malinterpretar la cita de David Herman. No significa " Es preferible usar siempre exportaciones únicas / predeterminadas en ES6 ", sino " Debido a que las exportaciones individuales son tan comunes, ES6 admite los valores predeterminados mejor y les dimos la sintaxis más dulce ".
Bergi
15

Si piensa que importes solo el azúcar de sintaxis para módulos de nodo, objetos y desestructuración, creo que es 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
fuente
9

Para comprender el uso de llaves en las importdeclaraciones, primero debe comprender el concepto de destrucción introducido en ES6

  1. Desestructuración 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. Desestructuración de matrices

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

    Usando la coincidencia de listas

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

    Usando el operador de propagación

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

Ahora que lo hemos eliminado, en ES6 puede exportar múltiples módulos. Luego puede hacer uso de la desestructuración de objetos como a continuación

Supongamos que tiene un módulo llamado module.js

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

Desea importar las funciones exportadas a index.js;

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

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

También puede usar diferentes nombres de variables como así

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

    pFname('Taylor');
    pLanme('Swift');
theTypan
fuente
Como está mostrando comparaciones con la desestructuración, agregaría la comparación de desestructuración equivalente a su último comentario: import {printFirstname as pFname, printLastname as pLname} from './module.js'es equivalente a:var foo = {printFirstname: 'p_f_n', printLastname: 'p_l_n'}; var { printFirstname:pFname, printLastname: pLname } = foo; pFname('Taylor'); pLname('Swift');
Adam Moisa
fanático del culturismo?
Tushar Pandey
@TusharPandey Soy fisicoculturista
theTypan
1
Creo que en cualquier explicación de importación y cuándo usar curlys en lugar de no usarlos, si no mencionas la destrucción de objetos, realmente no estás dando la mejor explicación. Una vez que aprendí sobre la desestructuración, nunca más pensé por qué uso el rizado, simplemente tenía sentido intuitivamente.
Eric Bishard el
6

Resumen ES6Módulos de :

exportaciones:

Tienes 2 tipos de exportaciones:

  1. Exportaciones nombradas
  2. Exportaciones predeterminadas, máximo 1 por módulo

Sintaxis:

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

Importaciones:

El tipo de exportación (es decir, exportaciones con nombre o predeterminadas) afecta cómo importar algo:

  1. Para una exportación con nombre tenemos que usar llaves y el nombre exacto como la declaración (es decir, variable, función o clase) que se exportó.
  2. Para una exportación predeterminada, podemos elegir el nombre.

Sintaxis:

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

Cosas de interes:

  1. Utilice una lista separada por comas entre llaves con el nombre correspondiente de la exportación para la exportación con nombre.
  2. Use un nombre de su elección sin llaves para una exportación predeterminada.

Alias

Siempre que desee cambiar el nombre de una importación con nombre, esto es posible mediante alias . La sintaxis para esto es la siguiente:

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

Ahora hemos importado importantData_1 pero el identificador es en myDatalugar de importantData_1.

Willem van der Veen
fuente
5

por lo general, cuando exporta una función, necesita usar {}

if you have export const x 

tu usas import {x} from ''

if you use export default const x 

necesita usar import X from '' aquí, puede cambiar X a la variable que desee

jadlmir
fuente
4

Las llaves ({}) se usan para importar enlaces con nombre y el concepto detrás de esto es la asignación de desestructuración

Puede encontrar una demostración simple de cómo funciona la declaración de importación con un ejemplo en mi propia respuesta a una pregunta similar en ¿ Cuándo usamos '{}' en las importaciones de JavaScript?

samuelj90
fuente
1
definitivamente tienes mi voto para la mejor respuesta corta!
Eric Bishard el
0

Las llaves se usan solo para importar cuando se nombra la exportación. Si la exportación es predeterminada, las llaves no se utilizan para importar.

Abhishek Kumar
fuente
0

Para una exportación predeterminada, no usamos {} cuando importamos.

p.ej

player.js

export default vx;

index.js

import vx from './player';

index.js ingrese la descripción de la imagen aquí

player.js ingrese la descripción de la imagen aquí

Si queremos importar todo lo que exportamos, usamos * ingrese la descripción de la imagen aquí

user260778
fuente