question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[RFC] Avoid or "prefer not to use" default exports

See original GitHub issue

Introduction

This discussion was initiated during the migration of eslint configs of material-ui/pickers and convention and code style consolidation. (https://github.com/mui-org/material-ui-pickers/pull/2004)

The problem

The core repository is using export default everywhere as a primary way to export React components. This RFC is about why it is not the best approach – the main problem of the default exports is implicit renames. And this unexpected renames leads to the following problems:

Consistent naming between all files

When export default is used it allows anonymous renames on the importing side:

export default function Modal() {
... 
}

// importing file
import Dialog from '../..'

Here it appeared that the component that has displayName="Modal" and actually is a Modal in the code reads like Dialog which is weird because it has its own defined name. This can also lead to the discrepancy between the component name in the component and display name in the dev tools.

Problems with refactoring

If we have an allowed implicit rename it could be tricky to find all the places when the component is used. And automated refactoring will also do nothing because rename is totally allowed

Make sure that for named exports there is a strong AST link for the rename import { Modal as Dialog } which is simplifying refactoring and make any rename explicit

Poor importing experience

Discoverability is very poor for default exports. You cannot explore a module with IntelliSense to see if it has a default export or not. With export default, you get nothing here (maybe it does export default / maybe it doesn’t (¯_(ツ)_/¯). And also it doesn’t autocomplete by the component name, while for named exports – it does.

import /* here */ from 'something';

Without export default you get a nice intellisense here:

import { /* here */ } from 'something';

More solid imports section

When there are no default exports through the codebase

import * as React from 'react'; 
import Typography from './somewhere' 
import { util } from './somewhereElse'
import Default, { andSomething } from '../'

Without

import * as React from 'react'; 
import { Typography }  from './somewhere' 
import { util } from './somewhereElse'
import { Default, andSomething } from '../'

And as huge bonus for typescript users: Props importing experience will be much clearer

import { Typography, TypographyProps } from '@material-ui/core'

For now, the only way to import props is:

import Typography { TypographyProps } from '@material-ui/core'

Normal flow of things

Originally the goal of export default (I am 99% sure) was intended to export something when we don’t really know what we exporting. The best case of default export power is dynamic examples – when we don’t really know which component we need to import and render. Or for example next.js’s page loader – when it also doesn’t know which pages it needs to process exactly.

When we have a specific object that we need to export – we should name it and use this name consistently through the codebase.

Potential problems

Default exports were loved by react community because of HOC. It was really useful to do

export default withStyles(Component)

It is not possible with named exports, but we could have a convention about naming private components in the file

function _Component() { 

}

export const Component = withStyles(_Component)

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:20
  • Comments:23 (23 by maintainers)

github_iconTop GitHub Comments

29reactions
oliviertassinaricommented, Jul 22, 2020

Still, I think that we should ask everybody as it impacts the whole codebase, across components (we would need to migrate the main repository if we forbid default exports) cc @mui-org/core-team, @DanailH, @PaulSavignano.

The vote is between:

10reactions
ryancogswellcommented, Jul 23, 2020

What this seems to come down to is that we are split fairly evenly between developers who work in ways where we don’t experience the problems this is trying to solve and therefore don’t see any benefit to the change, and another group using different habits, tools, refactoring approaches, etc. that see a clear benefit to the change.

I don’t think the 🎉 group has much chance of convincing the 👍 group that it will provide these same benefits to the 👍 group who have different work habits than the 🎉 group. So I think the main question should be “are there enough downsides to this change to deny the benefits of this change to the 🎉 group?”

My biggest concern is the impact outside of Material-UI. This is a change that would affect every single Material-UI import in many codebases. Obviously there would need to be a codemod to help with the change, but it still will seem — to a large portion of library users — like an arbitrary change with no benefit that forces slightly more verbose syntax. There will also be a portion of users that are pleased with the change (based on the sampling here), but I suspect the annoyed group will be significantly louder than the pleased group. Code samples on hundreds of stackoverflow questions will no longer work in v5 without changing the imports.

These aren’t massive problems, but it will be a nuisance to a large number of people and it will be a barrier to upgrading. Upgrading will feel a lot riskier if you have to change nearly every file that uses Material-UI (even if that change is automated).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Change: Prefer default export to no default export (#20) · Issues
All modules will always export named exports, meaning a future change will not affect the existing code.
Read more >
Why we have banned default exports in Javascript and you ...
Default exports were introduced mostly for easier interoperability with thousands CommonJS modules that were exporting single values like:
Read more >
Avoid ES6 default exports - Rajesh Naroth - Medium
It is very easy to confuse default exports vs named ones while importing from the same package. Ever paused wondering if you have...
Read more >
RFC 4880: OpenPGP Message Format
It does not deal with storage and implementation questions. It does, however, discuss implementation issues necessary to avoid security flaws.
Read more >
‪Module Cheatsheet ‬ | SamanthaMing.com
Default Export | Default Import export default 'value' import anyName from '. ... friend back with cash, which is like a default export...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found