Why Is `Export Default Const` invalid?
Asked Answered
S

8

696

I see that the following is fine:

const Tab = connect( mapState, mapDispatch )( Tabs );
export default Tab;

However, this is incorrect:

export default const Tab = connect( mapState, mapDispatch )( Tabs );

Yet this is fine:

export default Tab = connect( mapState, mapDispatch )( Tabs );

Can this be explained please why const is invalid with export default? Is it an unnecessary addition & anything declared as export default is presumed a const or such?

Shimberg answered 28/3, 2016 at 11:16 Comment(7)
esdiscuss.org/topic/…Concoction
export default Tab = connect( mapState, mapDispatch )( Tabs ); should be export default connect( mapState, mapDispatch )( Tabs );. You're exporting the result of the function call, not the variable Tab.Thunderclap
A const or let is required (and relevant) in the exporting module but irrelevant in the importing module, where the imported identifier is always read-only (cannot be assigned to). This still doesn't explain why the syntax of "export default" differs from non-default "export".Manhandle
Note: export default Tab = is a syntax error, Tab is undefined. The only way this would be valid syntax is if you had assigned Tab to something via let or var before... e.g let Tab; export default Tab = ... which is not good practice.Dareece
It's not a syntax error, assigning to undefined variables is valid JS. But most likely undesired behavior.Electromotor
@Electromotor Modules (export!) are always in strict mode. In this mode an assignment to some undeclared variable is not valid JS! Strictly speaking this is a semantic scoping error which prevents the module to be imported. Even that it is not strictly correct I'd accept if somebody calls this type of error to be a "syntax error". But you are right, if we nitpick, it is no syntax error. But if we nitpick, you are wrong at the same time, as it is not an undefined variable (which is valid JS) we are dealing here with, but it is an undeclared variable instead which is not valid JS (in modules).Brettbretz
I think what you're looking for is export default connect( mapState, mapDispatch )( Tabs ); - keep in mind that the var name is irrelevant when importing a default value; for this reason it makes sense that Tab, the var name, disappearsJadeite
P
514

const is like let, it is a LexicalDeclaration (VariableStatement, Declaration) used to define an identifier in your block.

You are trying to mix this with the default keyword, which expects a HoistableDeclaration, ClassDeclaration or AssignmentExpression to follow it.

Therefore it is a SyntaxError.


If you want to const something you need to provide the identifier and not use default.

export by itself accepts a VariableStatement or Declaration to its right.


The following is fineexport default Tab;

Tab becomes an AssignmentExpression as it's given the name default ?

export default Tab = connect( mapState, mapDispatch )( Tabs ); is fine

Here Tab = connect( mapState, mapDispatch )( Tabs ); is an AssignmentExpression.


Update: A different way to imagine the problem

If you're trying to conceptually understand this and the spec-reasoning above is not helping, think of it as "if default was a legal identifier and not a reserved token, what would be a different way to write export default Foo; and export default const Foo = 1; ?"

In this situation, the expanded way to write it would be

// pseudocode, this thought experiment is not valid JS

export default Foo;
// would be like
export const default = Foo;

export default const Foo = 1;
// would be like
export const default const Foo = 1;
// so would the following line make sense?
const bar const Foo = 1;

There is a valid argument the expansion should be something like

// pseudocode, this thought experiment is not valid JS

export default const Foo = 1;
// would be like
const Foo = 1;
export const default = Foo;

However, this then would become ambiguous per Sergey's comment, so it makes more sense to write this pattern explicitly instead.

Parhe answered 28/3, 2016 at 11:26 Comment(8)
The answer is how it is become an error. The question is still why? The one reason it prevent abuse of const in this way : export default const a=1, b=3, c=4;Bellow
"AFAIK the export in itself should not add anything to your current scope" This is not so accurate, because export const a = 1 adds a to your current context. And even with export default in case of classes, because export default class MyClass {} adds MyClass to your current context as well.Monteux
@SergeyOrlov agree that this explains how this generates an error, but sheds little light as to why it's necessary. Although I'm not sure that's the single reason, you should probably post that as a separate answer, not a comment to this one.Ashore
If I do the following: let a; export default a; and then update the variable a when it already has been imported into another module, why does the export default variable not update?Helio
My understanding is, for short, you can write const foo = function bar() {} and also const Foo = class Bar {}, but not const foo = const bar = 1. Same for export default, it's just like const foo =.Morette
The answer is for another question. Original question is unanswered.Levi
I'm with @Levi -- this answers why the parser rejects it as a syntax error, but does not explain why the grammar was designed to prevent export default const ..., a construct which seems to make perfect sense despite being illegal. I highly doubt that @Shimberg was asking about the parser.Barramunda
@Barramunda If you need a different way of thinking about it, consider export default like sugar for export const default =, so writing export default const foo = bar; would be equivalent to export const default = const foo = bar;, which wouldn't make sense as x y is a syntax error and const is a token which can't be an identifier so also would be an error (you cant const const = 1;)Parhe
S
93

You can also do something like this if you want to export default a const/let, instead of

const MyComponent = ({ attr1, attr2 }) => (<p>Now Export On other Line</p>);
export default MyComponent

You can do something like this, which I do not like personally.

let MyComponent;
export default MyComponent = ({ }) => (<p>Now Export On SameLine</p>);
Sampan answered 16/3, 2017 at 7:3 Comment(2)
Yep, that’d work — but it feels so wrong that I actually find myself wishing you hadn’t posted it. Somebody’s going to copy and paste that into their source code somewhere! 😬Barramunda
Agree export default function MyComponent({ attr1, attr2 }) should be preferred over the let MyComponent solutionRapier
S
30

If the component name is explained in the file name MyComponent.js, just don't name the component, keeps code slim.

import React from 'react'

export default (props) =>
    <div id='static-page-template'>
        {props.children}
    </div>

Update: Since this labels it as unknown in stack tracing, it isn't recommended

Update 2: I have only been using the es5 version below since it keeps names on stack traces and react dev tools.

import React from 'react'

export default function MyComponent(props) {
    return (<div id='static-page-template'>
        {props.children}
    </div>)
}
Sceptre answered 15/4, 2018 at 16:38 Comment(8)
Didn't you have issues with stacktraces ? For me it's causing displaying Unknown everywhere where is unnamed default exportSubstrate
@Substrate Yes it will display that way because it isn't named, so the component must be named "Unknown"Sceptre
While this works, without a doubt it's something every react developer outside of toy application development should strive to avoid at all costs.Peatroy
@lix I couldn't understand why one should avoid using this syntax. Would you please explain or share a link ? Thanks.Chrystel
@Chrystel Creating a component with no name is not good for the react component model and rendering.Peatroy
Looks clean however, also Dan Abramov suggests that we should use proper function/const names in component declaration: twitter.com/dan_abramov/status/1255229440860262400 ;) "- will show up as Anonymous in stack traces - will show up as Unknown in DevTools - won't be checked by React-specific lint rules - won't work with some features like Fast Refresh"Agranulocytosis
I'm a fan of export default function MyComponent(props) {Barramunda
Note that this question is not tagged react. It is a question about how to perform a default-export with a const value! IMO this is clearly the correct answer.Jadeite
R
16

The answer shared by Paul is the best one. To expand more,

There can be only one default export per file. Whereas there can be more than one const exports. The default variable can be imported with any name, whereas const variable can be imported with it's particular name.

var message2 = 'I am exported';
export default message2;
export const message = 'I am also exported'

At the imports side we need to import it like this:

import { message } from './test';

or

import message from './test';

With the first import, the const variable is imported whereas, with the second one, the default one will be imported.

Radcliff answered 13/7, 2018 at 17:6 Comment(4)
Not sure if this is a typo but default export variable is message2 and so it should be import message2 from './test';. Just to clarify further - only named exports can use curly braces ({}). Since there can only be one default export per module file, importing default vars doesn't require them as in importing message2.Semiconductor
@StackUndefined It is intended. Just tested it in a Expo app. So the default export can be import as whatever name you want to import as.Mountford
this answer is not answering the question. did you accidently post it in wrong question?Estimative
@StackUndefined the default exports can be imported with any name/identifier we like.Variolous
D
10

With export default, you don't export the name of, in this case, the variable.

wrong:

export default const Tab = connect( mapState, mapDispatch )( Tabs );

right:

export default connect( mapState, mapDispatch )( Tabs );

You can import it on any name you like

Demon answered 2/5, 2022 at 14:37 Comment(0)
C
9

Paul's answer is the one you're looking for. However, as a practical matter, I think you may be interested in the pattern I've been using in my own React+Redux apps.

Here's a stripped-down example from one of my routes, showing how you can define your component and export it as default with a single statement:

import React from 'react';
import { connect } from 'react-redux';

@connect((state, props) => ({
    appVersion: state.appVersion
    // other scene props, calculated from app state & route props
}))
export default class SceneName extends React.Component { /* ... */ }

(Note: I use the term "Scene" for the top-level component of any route).

I hope this is helpful. I think it's much cleaner-looking than the conventional connect( mapState, mapDispatch )( BareComponent )

Claresta answered 1/9, 2017 at 16:19 Comment(2)
Too bad decorators can't seem to be used on a function componentMoxley
@EricKim Bummer. But, it's worth bearing in mind that the decorator spec isn't final yet. Maybe functional components can't be decorated using the "legacy" decorator, but I don't know if that's due to a limitation of the legacy design, or because the implementation of legacy decorators is incomplete or buggy. FWIW: @connect is the only decorator I use, I only use it with components that are attached to a redux store, almost every one of those is a "route," and almost every route should have state (and therefore cannot be a pure function).Claresta
B
8

default is basically const someVariableName

You don't need a named identifier because it's the default export for the file and you can name it whatever you want when you import it, so default is just condensing the variable assignment into a single keyword.

Botnick answered 21/10, 2019 at 23:12 Comment(1)
"default is basically const foo", not exactly, at least export default a = 1;a=2; gives assignment to undeclared variable a and export const a = 1;a=2; gives invalid assignment to const 'a'. Moreover, export default a = 1; allows BOTH unnamed (default) import and named import while export const a = 1; only has named import. Totally inaccurate answer.Sapor
B
3

In short

JavaScript does not support export default along with const.
export default can be used along with expressions, functions and classes.

Wrong:

export default const a = 10, b = 20;

It is because we cannot identify which is the default out of a and b at the time of import.

Right

const a = 10, b = 20;
export default a;

Or simply

Don't use default with const:

export const a = 10, b = 20;

Note: Although only 1 export default is allowed in a JavaScript module, multiple exports are allowed.

Reference

Beamon answered 11/12, 2023 at 1:41 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.