Warum ist "Export Default Const" ungültig?

351

Ich sehe, dass Folgendes in Ordnung ist:

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

Dies ist jedoch falsch:

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

Doch das ist in Ordnung:

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

Kann dies bitte erklärt werden, warum constmit ungültig ist export default? Ist es eine unnötige Ergänzung und irgendetwas, das als export defaulta constoder so vermutet wird ?

Kayote
quelle
1
export default Tab = connect( mapState, mapDispatch )( Tabs );sollte sein export default connect( mapState, mapDispatch )( Tabs );. Sie exportieren das Ergebnis des Funktionsaufrufs, nicht die Variable Tab.
ThaJay
2
Eine Konstante oder ein Let ist im Exportmodul erforderlich (und relevant), im Importmodul jedoch irrelevant, wo die importierte Kennung immer schreibgeschützt ist (nicht zugewiesen werden kann). Dies erklärt immer noch nicht, warum sich die Syntax von "Standard exportieren" von der nicht standardmäßigen "Export" unterscheidet.
Denis Howe

Antworten:

303

constist wie let, es ist LexicalDeclaration ( VariableStatement, Deklaration ) verwendet , um eine Kennung in dem Block zu definieren.

Sie versuchen, dies mit dem defaultSchlüsselwort zu mischen , das erwartet , dass eine HoistableDeclaration, ClassDeclaration oder AssignmentExpression darauf folgt.

Daher ist es ein SyntaxError .


Wenn Sie constetwas möchten, müssen Sie die Kennung angeben und nicht verwenden default.

exportselbst akzeptiert eine VariableStatement oder Deklaration zu seiner Rechten.


AFAIK Der Export an sich sollte Ihrem aktuellen Umfang nichts hinzufügen.


Das Folgende ist in Ordnungexport default Tab;

Tabwird ein AssignmentExpression, da er den Standardnamen erhält ?

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

Hier Tab = connect( mapState, mapDispatch )( Tabs );ist ein AssignmentExpression .

Paul S.
quelle
27
Die Antwort ist, wie es zu einem Fehler wird. Die Frage ist immer noch warum? Der einzige Grund, warum es den Missbrauch von const auf diese Weise verhindert: Exportieren Sie die Standardkonstante a = 1, b = 3, c = 4;
Sergey Orlov
7
"AFAIK the export in itself should not add anything to your current scope"Das ist nicht so genau, weil export const a = 1fügt azu Ihrem aktuellen Kontext. Und selbst mit export defaultbei Klassen, da export default class MyClass {}fügt MyClasszu Ihrem aktuellen Kontext als auch.
Ernesto
4
@SergeyOrlov stimmt zu, dass dies erklärt, wie dies einen Fehler erzeugt, aber wenig Licht darauf wirft, warum dies notwendig ist. Obwohl ich nicht sicher bin, ob dies der einzige Grund ist, sollten Sie dies wahrscheinlich als separate Antwort und nicht als Kommentar zu dieser Antwort posten.
Herick
Wenn ich Folgendes tue: let a; export default a;und dann die Variable a aktualisiere, wenn sie bereits in ein anderes Modul importiert wurde, warum wird die Standardvariable für den Export nicht aktualisiert?
K - Die Toxizität in SO nimmt zu.
Mein Verständnis ist, kurz gesagt, Sie können schreiben const foo = function bar() {}und auch const Foo = class Bar {}, aber nicht const foo = const bar = 1. Das gleiche gilt für export default, es ist einfach so const foo =.
Zetavg
47

Sie können auch so etwas tun, wenn Sie stattdessen standardmäßig eine const / let exportieren möchten

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

Sie können so etwas tun, was ich persönlich nicht mag.

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

Wenn der Komponentenname im Dateinamen erläutert wird, MyComponent.jsbenennen Sie die Komponente einfach nicht, da der Code schlank bleibt.

import React from 'react'

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

Update : Da dies in der Stapelverfolgung als unbekannt gekennzeichnet ist, wird es nicht empfohlen

Kevin Danikowski
quelle
14
Hatten Sie keine Probleme mit Stacktraces? Für mich ist es die Anzeige Unknownüberall dort, wo unbenannter Standardexport ist
Jurosh
2
Während dies funktioniert, ist es ohne Zweifel etwas, das jeder Reaktionsentwickler außerhalb der Entwicklung von Spielzeuganwendungen unbedingt vermeiden sollte .
li x
1
@lix Ich konnte nicht verstehen, warum man diese Syntax vermeiden sollte. Würden Sie bitte einen Link erklären oder teilen? Vielen Dank.
Sudip
3
@sudip Das Erstellen einer Komponente ohne Namen ist nicht gut für das Reaktionskomponentenmodell und das Rendern.
li x
1
Sieht jedoch sauber aus, auch Dan Abramov schlägt vor, dass wir in der Komponentendeklaration die richtigen Funktions- / Konstantennamen verwenden sollten: twitter.com/dan_abramov/status/1255229440860262400 ;) "- wird in Stapelspuren als anonym angezeigt - wird in DevTools als unbekannt angezeigt - wird nicht durch reaktionsspezifische Flusenregeln überprüft - funktioniert nicht mit einigen Funktionen wie Fast Refresh "
Zoltan
9

Pauls Antwort ist die, die Sie suchen. Aus praktischen Gründen könnten Sie jedoch an dem Muster interessiert sein, das ich in meinen eigenen React + Redux-Apps verwendet habe.

Hier ist ein reduziertes Beispiel von einer meiner Routen, das zeigt, wie Sie Ihre Komponente definieren und mit einer einzigen Anweisung als Standard exportieren können:

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

(Hinweis: Ich verwende den Begriff "Szene" für die oberste Komponente einer Route.)

Ich hoffe das ist hilfreich. Ich denke, es sieht viel sauberer aus als das konventionelleconnect( mapState, mapDispatch )( BareComponent )

Tom
quelle
Schade, dass Dekorateure nicht für eine Funktionskomponente verwendet werden können
Eric Kim
@ EricKim Bummer. Es ist jedoch zu beachten, dass die Dekorationsspezifikation noch nicht endgültig ist. Möglicherweise können funktionale Komponenten nicht mit dem "Legacy" -Dekorator dekoriert werden, aber ich weiß nicht, ob dies auf eine Einschränkung des Legacy-Designs zurückzuführen ist oder ob die Implementierung von Legacy-Dekoratoren unvollständig oder fehlerhaft ist. FWIW: @connectist der einzige Dekorateur, den ich verwende. Ich verwende ihn nur mit Komponenten, die an einen Redux-Speicher angeschlossen sind. Fast jede dieser Komponenten ist eine "Route", und fast jede Route sollte einen Status haben (und kann daher keine reine Funktion sein.) .
Tom
8

Die Antwort von Paulus ist die beste. Um mehr zu erweitern,

Es kann nur einen Standardexport pro Datei geben. Während es mehr als einen konstanten Export geben kann. Die Standardvariable kann mit einem beliebigen Namen importiert werden, während die const-Variable mit ihrem bestimmten Namen importiert werden kann.

var message2 = 'Ich werde exportiert';

Standardnachricht exportieren2;

export const message = 'Ich werde auch exportiert'

Auf der Importseite müssen wir es wie folgt importieren:

{message} aus './test' importieren;

oder

Nachricht aus './test' importieren;

Beim ersten Import wird die Variable const importiert, während beim zweiten Import die Standardvariable importiert wird.

Ingwer Bier
quelle
Liebe deine Antwort, danke!
White159
0

default ist im Grunde const someVariableName

Sie benötigen keinen benannten Bezeichner, da dies der Standardexport für die Datei ist und Sie sie beim Importieren beliebig benennen können, sodass defaultdie Variablenzuweisung nur in einem einzigen Schlüsselwort zusammengefasst wird.

Mani Gandham
quelle
-3

Für mich ist dies nur eine von vielen Eigenheiten (Betonung der Redewendung (t)) des Typoskripts, die dazu führen, dass sich die Leute die Haare ausreißen und die Entwickler verfluchen. Vielleicht könnten sie daran arbeiten, verständlichere Fehlermeldungen zu finden.

Großer Hund
quelle