为什么“导出默认常量”无效?


348

我看到以下情况很好:

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

但是,这是不正确的:

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

但这很好:

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

请解释一下为什么 const无效export default吗?它是一个不必要的加法,并且export default被假定为const诸如此类的任何东西吗?



1
export default Tab = connect( mapState, mapDispatch )( Tabs );应该是export default connect( mapState, mapDispatch )( Tabs );。您正在导出函数调用的结果,而不是变量Tab。
ThaJay

2
在导出模块中需要(或相关)const或let,但在导入模块中则不相关,在导入模块中,导入的标识符始终是只读的(无法分配给)。这仍然不能解释为什么“ export default”的语法不同于非默认“ export”的语法。
丹尼斯·豪

Answers:


300

const就像let它是一个LexicalDeclarationVariableStatement,),用于在您的块中定义标识符。

您正在尝试将其与default关键字混合使用,该关键字需要HoistableDeclaration,ClassDeclarationAssignmentExpression跟随它。

因此,它是一个SyntaxError错误


如果您想要const某些内容,则需要提供标识符而不要使用default

export本身接受变量声明声明的权利。


AFAIK导出本身不应该在当前范围内添加任何内容。


以下很好export default Tab;

Tab成为一个AssignmentExpression,因为它被赋予了默认 名称

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

Tab = connect( mapState, mapDispatch )( Tabs );是一个AssignmentExpression


27
答案是它如何成为错误。问题仍然是为什么?它以这种方式防止const滥用的原因之一:导出默认const a = 1,b = 3,c = 4;
谢尔盖·奥尔洛夫

7
"AFAIK the export in itself should not add anything to your current scope"这不太准确,因为export const a = 1会增加a您的当前上下文。甚至export default在使用类的情况下,因为也会export default class MyClass {}增加MyClass当前的上下文。
埃内斯托

4
@SergeyOrlov同意,这可以解释这是如何产生错误的,但对于必要的原因却鲜有了解。尽管我不确定这是唯一的原因,但您可能应该将其发布为单独的答案,而不是对此内容发表评论。
Herick

如果我执行以下操作:let a; export default a;然后在变量a已经导入到另一个模块中时对其进行更新,为什么导出默认变量不更新?
K-SO的毒性在增加。

我的理解是,短,你可以写const foo = function bar() {},也const Foo = class Bar {},但不是const foo = const bar = 1。同样export default,就像const foo =
zetavg

47

如果您要导出默认的const / let而不是

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

您可以执行类似我个人不喜欢的操作。

let MyComponent;
export default MyComponent = ({ }) => (<p>Now Export On SameLine</p>);

18

如果在文件名中说明了组件名称MyComponent.js,请不要命名该组件,以使代码保持苗条。

import React from 'react'

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

更新:由于在堆栈跟踪中将其标记为未知,因此不建议使用


14
您没有stacktrace的问题吗?对我来说,这导致Unknown到处显示未命名的默认出口
Jurosh

2
尽管这样做有效,但毫无疑问,玩具应用程序开发之外的每个开发人员都应尽一切努力避免这种情况。
li x

1
@lix我不明白为什么要避免使用这种语法。您能解释一下还是分享一个链接?谢谢。
sudip

3
@sudip创建没有名称的组件不利于react组件模型和渲染。
li x

1
但是看起来很干净,Dan Abramov也建议我们在组件声明中使用正确的函数/ const名称:twitter.com/dan_abramov/status/1255229440860262400 ;)“-在堆栈跟踪中将显示为匿名-在DevTools中将显示为Unknown -不会由React特定的棉绒规则检查-不能与“快速刷新”等某些功能一起使用”
Zoltan

9

Paul的答案就是您要寻找的答案。但是,实际上,我想您可能会对我在自己的React + Redux应用程序中使用的模式感兴趣。

这是我的一条路线的精简示例,显示了如何定义组件并将其作为默认语句导出为单个语句:

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 { /* ... */ }

(注意:我将术语“场景”用于任何路线的顶层组件)。

我希望这是有帮助的。我认为它比传统的看起来更干净connect( mapState, mapDispatch )( BareComponent )


不好的装饰器似乎无法在功能组件上使用
Eric Kim

@EricKim Bummer。但是,值得记住的是装饰器规范尚未​​最终确定。可能无法使用“旧式”装饰器装饰功能组件,但是我不知道这是由于传统设计的局限性还是因为传统装饰器的实现不完整或有问题。FWIW:@connect是我使用的唯一装饰器,我仅将其与连接到redux存储的组件一起使用,几乎每个组件都是“路由”,并且几乎每个路由都应具有状态(因此不能是纯函数) 。
汤姆(Tom)

8

保罗的答案是最好的。要扩展更多,

每个文件只能有一个默认导出。而可以有多个const出口。可以使用任何名称导入默认变量,而可以使用特定名称导入const变量。

var message2 ='我已导出';

导出默认message2;

export const message ='我也被导出'

在导入方面,我们需要这样导入:

从“ ./test”导入{消息};

要么

从“ ./test”导入消息;

在第一次导入时,将导入const变量,而在第二次导入时,将导入默认变量。


爱你的答案,谢谢!
White159

0

default 基本上是 const someVariableName

您不需要命名标识符,因为它是文件的默认导出,并且您可以在导入文件时随意命名,因此default只需将变量赋值压缩为一个关键字即可。


-3

对我来说,这只是打字稿的许多特质之一(强调idio(t)),它使人们拔头发并诅咒开发人员。也许他们可以努力提出更多可理解的错误消息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.