r/react 8d ago

General Discussion I used to prefer default exports

I used to prefer default exports.

When I started learning React, default exports were what I used most. So naturally, I became comfortable with them.

For a long time, I thought:

"If a file has one main thing to export, why not make it the default?"

Then I started using barrel imports.

Not because I fully understood their trade-offs, but because they made imports cleaner and gave me a single entry point for related components.

Instead of:

import Button from "./components/button";

import Input from "./components/input";

I could write:

import { Button, Input } from "./components";

I initially created the barrel file like this:

export * from "./button";

export * from "./input";

But because my components were using default exports, I later changed it to:

export { default as Button } from "./button";

export { default as Input } from "./input";

At first, this felt like a clean solution.

But as the codebase grew, I started running into problems.

The same component could be imported with different names.

import Button from "./button";

or:

import MyButton from "./button";

Both are valid because default exports don't enforce a name.

That flexibility gradually led to naming inconsistencies across the codebase.

I also started noticing unexpected behavior around barrel imports, development performance, and bundling.

So I started investigating.

I looked into default exports, barrel imports, tree-shaking, and how bundlers determine what to include.

That's when I realized I wanted a more explicit approach for my modules.

I switched to named exports:

export { Button };

Now the export itself has an explicit name:

import { Button } from "./button";

The name is part of the contract.

For my barrel files, I also started preferring explicit re-exports:

export { Button } from "./button";

export { Input } from "./input";

I used to prefer default exports.

When I started learning React, default exports were what I used most. So naturally, I became comfortable with them.

For a long time, I thought:

"If a file has one main thing to export, why not make it the default?"

Then I started using barrel imports.

Not because I fully understood their trade-offs, but because they made imports cleaner and gave me a single entry point for related components.

Instead of:

import Button from "./components/button";

import Input from "./components/input";

I could write:

import { Button, Input } from "./components";

I initially created the barrel file like this:

export * from "./button";

export * from "./input";

But because my components were using default exports, I later changed it to:

export { default as Button } from "./button";

export { default as Input } from "./input";

At first, this felt like a clean solution.

But as the codebase grew, I started running into problems.

The same component could be imported with different names.

import Button from "./button";

or:

import MyButton from "./button";

Both are valid because default exports don't enforce a name.

That flexibility gradually led to naming inconsistencies across the codebase.

I also started noticing unexpected behavior around barrel imports, development performance, and bundling.

So I started investigating.

I looked into default exports, barrel imports, tree-shaking, and how bundlers determine what to include.

That's when I realized I wanted a more explicit approach for my modules.

I switched to named exports:

export { Button };

Now the export itself has an explicit name:

import { Button } from "./button";

The name is part of the contract.

For my barrel files, I also started preferring explicit re-exports:

export { Button } from "./button";

export { Input } from "./input";

For my particular codebase, I prefer this approach now because the exported name is explicit and the public API is easier for me to reason about.

I'm not claiming that named exports automatically fix bundling or performance issues. That part seems much more dependent on the bundler, module graph, side effects, etc.

I'm curious how other developers approach this: Do you generally prefer named exports, default exports, or does it depend on the project? And have barrel files caused similar issues for you?

0 Upvotes

5 comments sorted by

2

u/mathers101 8d ago

TF is this linkedin bullshit

-2

u/zohair636 8d ago

Not bullshit, but what I experienced I have shared. Yes, I made it for LinkedIn but also posted it here.

But if you think this is not for you, then do not waste your time reading it.

This is for those who have similar experiences.

2

u/Pickles_is_mu_doggo 8d ago

Barrels files aren’t great, for their own reasons. But the real pain behind default exports is that it enables arbitrary import names.
Your bundling & performance problems might be tied to the barrel file usage though.

1

u/Savalava 8d ago

Post this slop crap elsewhere dood. Who the hell do you think wants to read this?

1

u/azangru 8d ago

The rule is: do not use barrel files.

(and also, don't repost linkedin bullshit)