Search code examples
javascriptreactjsecmascript-6exportcreate-react-app

Why cannot export function inside default object


I'm wondering why this is not valid on an application created using create-react-app:

/***** myLib.js *****/
const multiplyByTwo = val => val * 2;

export default { multiplyByTwo };

Nor:

/***** myLib.js *****/
let multiplyByTwo = val => val * 2;

export default { multiplyByTwo };

Neither:

/***** myLib.js *****/
function multiplyByTwo(val) { return val * 2; };

export default { multiplyByTwo };

Then, in another file:

/***** main.js *****/
import { multiplyByTwo } from './myLib'

console.log(multiplyByTwo(10));

When I try to compile it, I get this error:

Failed to compile.

./src/main.js
Attempted import error: 'multiplyByTwo' is not exported from './myLib'

However, this is valid:

/***** myLib.js *****/
export const multiplyByTwo = val => val * 2;

Also this:

/***** myLib.js *****/
export let multiplyByTwo = val => val * 2;

Solution

  • The difference is between named exports and the default export.

    When you use export default <expression>, that expression becomes available for importing elsewhere when you use import exprName from .... The module is exporting expression as the default export, and import exprName takes the default export of that module and puts it into exprName. But the syntax import { exprName } is something entirely different; that syntax indicates that you want to extract the named export of name exprName from the module. It's not destructuring, even though it looks a lot like it.

    Your myLib.js does not have a named export of multiplyByTwo (it only has a default export of an object, which has a property named multiplyByTwo), so

    import { multiplyByTwo } from './myLib'
    

    fails.

    It would make the most sense to use a named export instead from myLib:

    export const multiplyByTwo = val => val * 2;
    

    and then it can be imported with the import { multiplyByTwo } syntax you're using elsewhere.

    Another option, using the same code in your original myLib, would be to import the default exported object, and then destructure it after importing:

    import myLib from './myLib';
    const { multiplyByTwo } = myLib;
    

    But that looks a bit odd.