85

I was under the impression that this syntax:

import Router from 'react-router';
var {Link} = Router;

has the same final result as this:

import {Link} from 'react-router';

Can someone explain what the difference is?

(I originally thought it was a React Router Bug.)

Guy
  • 65,082
  • 97
  • 254
  • 325
  • 5
    Unfortunately they have the same shorthand syntax, but if you check their long forms they are clearly different: `var {"Link": Link} = Router;` vs `import {Link as Link} from '…';` – Bergi Nov 04 '15 at 15:30

3 Answers3

128
import {Link} from 'react-router';

imports a named export from react-router, i.e. something like

export const Link = 42;

import Router from 'react-router';
const {Link} = Router;

pulls out the property Link from the default export, assuming it is an object, e.g.

export default {
  Link: 42
};

(the default export is actually nothing but a standardized named export with the name "default").

See also export on MDN.

Complete example:

// react-router.js
export const Link = 42;
export default {
  Link: 21,
};


// something.js
import {Link} from './react-router';
import Router from './react-router';
const {Link: Link2} = Router;

console.log(Link); // 42
console.log(Link2); // 21

With Babel 5 and below I believe they have been interchangeable because of the way ES6 modules have been transpiled to CommonJS. But those are two different constructs as far as the language goes.

Lynn
  • 10,425
  • 43
  • 75
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
15

To do this:

import {purple, grey} from 'themeColors';

Without repeating export const for each symbol, just do:

export const
  purple = '#BADA55',
  grey = '#l0l',
  gray = grey,
  default = 'this line actually causes an error';
Devin Rhode
  • 23,026
  • 8
  • 58
  • 72
0

Except for different exports, it may also lead to different bundled code by WebPack when using two variant ways to destruct ESM modules:

// react-router
export function Link(str) { /* ... */ }
  1. Destruct within the import statement:

    import {Link} from 'react-router';
    
    Link('1');
    Link('2');
    
    // WebPack output
    var util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1);
    (0,util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__.Link)('1');
    (0,util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__.Link)('2');
    
  2. Use destructuring syntax:

    import * as Router from 'react-router';
    const {Link} = Router;
    
    Link('1');
    Link('2');
    
    // WebPack output:
    var util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1);
    const {Link} = util_mobileValidator__WEBPACK_IMPORTED_MODULE_3__;
    Link(1);
    Link(2);
    

As you can see in the output example above where there is redundant code, which is not good for optimization when trying to uglify via UglifyJS, or Terser.

PuiMan Cheui
  • 94
  • 1
  • 9