Understanding Named vs. Default Exports

🌐

This post has been translated by DeepL . Please let us know if there are any mistranslations!

Named Export

Named Export is used to export multiple variables, functions, and classes from a module. Each exported element has a name, which allows you to selectively import only the parts you need.

For example, write code like this

// utils.js
export const PI = 3.14;

export function add(a, b) {
  return a + b;
}

export class Calculator {
  subtract(a, b) {
    return a - b;
  }
}

After exporting as above, you can import it where you use it like below.

// main.js
import { PI, add, Calculator } from './utils.js';

console.log(PI); // 3.14
console.log(add(2, 3)); // 5

const calc = new Calculator();
console.log(calc.subtract(5, 2)); // 3

Default Export

Default Export is used to export a single default value from a module. You can only have one Default Export per module, and you can name it when importing.

// logger.js
export default function log(message) {
  console.log(message);
}

Import like this.

// app.js
import log from './logger.js';

log('Hello!'); // Hello!

Key differences

  1. Number of exports

    • Named Export: multiple possible
    • Default Export: only one per module
  2. Import syntax

    • Named Export: import { name1, name2 } from './module';
    • Default Export: import anyName from './module';
  3. Renaming

    • Named Export: import { originalName as newName } from './module';
    • Default Export: free to name on import
  4. Full import

    • Named Export: import * as moduleName from './module';
    • Default Export: No need for a full import because they are already treated as one object
  5. Dynamic imports

    • Named Export: import('./module').then(module => module.namedExport)
    • Default Export: import('./module').then(module => module.default)

When should you use one over the other?

  • Named Export: Useful when you want to export multiple utility functions or variables from a module and selectively import and use them.
  • Default Export: Use this to export the main functionality or classes of a module.

Utilizing index.js

Let's take a look at a project with a folder structure like this

Image.png

Each component is exported as a Named Export as shown below.

const TestComponent = () => {
  return <div></div>;
};

export { TestComponent };

To write it, we'll import it like this

import { TestComponent, TestComponent2 } from '@/components/ui';

function App() {
  return (
    <div>
      <TestComponent />
      <TestComponent2 />
    </div>
  );
}

export default App;

Let's create index.js(ts) file like below and export it again.

// Named Export
export { TestComponent } from './TestComponent';
export { TestComponent2 } from './TestComponent2';

// Default Export
export { default as TestComponent } from './TestComponent';
export { default as TestComponent2 } from './TestComponent2';

Then, where we import, we can import a little cleaner like this

import { TestComponent, TestComponent2 } from '@/components/ui';

function App() {
  return (
    <div> <TestComponent
      <TestComponent /> <TestComponent1
      <TestComponent2 />
    </div> </div
  );
}

} export default App;

Pros and cons of using index.js

Pros

  • Simplifies module structure by acting as an entry point into a directory.
  • You can export the contents of multiple files in one, making your import statements concise.
  • Changes to the directory structure don't affect external code.

Cons

  • If you put too much content into index.js, the file can become cluttered.

Avoid Export Default

The documentationsays to avoid using Export Default. (At least in a TypeScript project?) The main reasons are as follows

No support for renaming

When you rename something in the IDE through refactoring, it doesn't do it automatically. For example, if you rename TestComponent to TestComponent2, it won't change in the import part. However, if you use Named Export, it does.

Inconsistency due to renaming freedom

  • Withdefault export, you can use any name on import, which means that the same module can be used with different names in different files.
  • This can lead to inconsistency and confusion in your code.

Lack of type information

  • The default exportdoes not provide type information, so it can be unclear what type of object or function is being exported.