Dlaczego `Export Default Const` jest nieprawidłowy?

352

Widzę, że wszystko jest w porządku:

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

Jest to jednak niepoprawne:

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

Ale to jest w porządku:

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

Czy można to wyjaśnić, dlaczego constjest nieważny export default? Czy jest to niepotrzebny dodatek i cokolwiek zadeklarowane jako export defaultdomniemane const?

Kayote
źródło
1
export default Tab = connect( mapState, mapDispatch )( Tabs );powinno być export default connect( mapState, mapDispatch )( Tabs );. Eksportujesz wynik wywołania funkcji, a nie zmienną Tab.
ThaJay,
2
Wymagana stała lub let (i odpowiednia) w module eksportującym, ale nieistotna w module importującym, gdzie importowany identyfikator jest zawsze tylko do odczytu (nie można go przypisać). To wciąż nie wyjaśnia, dlaczego składnia „domyślnego eksportu” różni się od niestandardowej „eksportu”.
Denis Howe,

Odpowiedzi:

305

constjest jak let, to jest Deklaracja Lexical ( VariableStatement, Deklaracja ) używana do definiowania identyfikatora w twoim bloku.

Próbujesz połączyć to ze defaultsłowem kluczowym, które oczekuje , że podąży za nim deklaracja HoistableDeclaration, ClassDeclaration lub AssignmentExpression .

Dlatego jest to błąd SyntaxError .


Jeśli chcesz constczegoś, musisz podać identyfikator, a nie używać default.

exportsam przyjmuje zmienne oświadczenie lub deklarację po swojej prawej stronie.


AFAIK sam eksport nie powinien niczego dodawać do twojego obecnego zakresu.


Wszystko w porządkuexport default Tab;

Tabstaje się wyrażeniem AssignmentExpression, ponieważ ma domyślną nazwę ?

export default Tab = connect( mapState, mapDispatch )( Tabs ); jest w porządku

Tutaj Tab = connect( mapState, mapDispatch )( Tabs );jest AssignmentExpression .

Paul S.
źródło
27
Odpowiedź brzmi: jak stał się błędem. Pytanie wciąż brzmi dlaczego? Jedyny powód, dla którego zapobiega to nadużywaniu const w ten sposób: eksportuj domyślną const a = 1, b = 3, c = 4;
Sergey Orlov
7
"AFAIK the export in itself should not add anything to your current scope"To nie jest tak dokładne, ponieważ export const a = 1dodaje ado twojego obecnego kontekstu. I nawet export defaultw przypadku klas, ponieważ również export default class MyClass {}dodaje MyClassdo twojego obecnego kontekstu.
Ernesto,
4
@SergeyOrlov zgadza się, że wyjaśnia to, w jaki sposób generuje błąd, ale rzuca niewiele światła na to, dlaczego jest to konieczne. Chociaż nie jestem pewien, czy jest to jedyny powód, prawdopodobnie powinieneś opublikować to jako osobną odpowiedź, a nie komentarz do tego.
Herick,
Jeśli wykonam następujące czynności: let a; export default a;a następnie zaktualizuję zmienną a, gdy już została zaimportowana do innego modułu, dlaczego domyślna zmienna eksportu nie zostanie zaktualizowana?
K - Toksyczność w SO rośnie.
Moje zrozumienie jest, w skrócie można napisać const foo = function bar() {}, a także const Foo = class Bar {}, ale nie const foo = const bar = 1. To samo dotyczy export default, tak po prostu const foo =.
zetavg
47

Możesz również zrobić coś takiego, jeśli chcesz wyeksportować domyślną const / let zamiast

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

Możesz zrobić coś takiego, czego osobiście nie lubię.

let MyComponent;
export default MyComponent = ({ }) => (<p>Now Export On SameLine</p>);
Adeel Imran
źródło
19

Jeśli nazwa komponentu jest wyjaśniona w nazwie pliku MyComponent.js, po prostu nie nazywaj komponentu, kod pozostanie wąski.

import React from 'react'

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

Aktualizacja : Ponieważ jest to nieznane w śledzeniu stosu, nie jest zalecane

Kevin Danikowski
źródło
14
Nie miałeś problemów z stacktraces? Dla mnie powoduje wyświetlanie Unknownwszędzie tam, gdzie domyślny jest eksport bez nazwy
Jurosh
2
Chociaż to działa, bez wątpienia jest to coś, na co każdy programista poza tworzeniem aplikacji zabawkowych powinien starać się unikać za wszelką cenę.
li x
1
@lix Nie mogłem zrozumieć, dlaczego należy unikać używania tej składni. Czy mógłbyś wyjaśnić lub udostępnić link? Dzięki.
sudip
3
@sudip Utworzenie komponentu bez nazwy nie jest dobre dla modelu komponentów reagowania i renderowania.
li x
1
Wygląda jednak czysto, również Dan Abramov sugeruje, że powinniśmy używać poprawnych nazw funkcji / stałych w deklaracji komponentu: twitter.com/dan_abramov/status/1255229440860262400 ;) "- pojawi się jako Anonim w śladach stosu - pojawi się jako Nieznany w DevTools - nie będzie sprawdzany według reguł dotyczących reakcji React - nie będzie działać z niektórymi funkcjami, takimi jak Fast Refresh ”
Zoltan
9

Odpowiedź Paula jest tą, której szukasz. Jednak ze względów praktycznych myślę, że możesz być zainteresowany wzorcem, którego używałem w moich własnych aplikacjach React + Redux.

Oto uproszczony przykład z jednej z moich tras, pokazujący, jak można zdefiniować komponent i wyeksportować go jako domyślny za pomocą pojedynczej instrukcji:

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

(Uwaga: używam terminu „Scena” dla komponentu najwyższego poziomu dowolnej trasy).

Mam nadzieję, że to jest pomocne. Myślę, że jest znacznie czystszy niż konwencjonalnyconnect( mapState, mapDispatch )( BareComponent )

Tomek
źródło
Szkoda, że ​​dekoratorzy nie mogą być zastosowani w komponencie funkcyjnym
Eric Kim,
@EricKim Bummer. Warto jednak pamiętać, że specyfikacja dekoratora nie jest jeszcze ostateczna. Być może funkcjonalne komponenty nie mogą być dekorowane przy użyciu „starszego” dekoratora, ale nie wiem, czy jest to spowodowane ograniczeniem starszego projektu, czy też dlatego, że implementacja starszych dekoratorów jest niekompletna lub błędna. FWIW: @connectjest jedynym dekoratorem, którego używam, używam go tylko z komponentami, które są podłączone do magazynu redux, prawie każda z nich jest „trasą” i prawie każda trasa powinna mieć stan (i dlatego nie może być czystą funkcją) .
Tom
8

Odpowiedź udzielona przez Paula jest najlepsza. Aby rozwinąć więcej,

Może być tylko jeden domyślny eksport na plik. Podczas gdy może być więcej niż jeden stały eksport. Zmienną domyślną można zaimportować pod dowolną nazwą, natomiast zmienną const można zaimportować o określonej nazwie.

var message2 = „Jestem eksportowany”;

eksportuj domyślną wiadomość2;

export const message = „Jestem również eksportowany”

Po stronie importu musimy go zaimportować w następujący sposób:

import {message} z './test';

lub

zaimportuj wiadomość z „./test”;

Przy pierwszym imporcie zmienna const jest importowana, podczas gdy przy drugim importowana jest zmienna domyślna.

Piwo imbirowe
źródło
0

default jest w zasadzie const someVariableName

Nie potrzebujesz nazwanego identyfikatora, ponieważ jest to domyślny eksport pliku i możesz go nazwać, kiedy chcesz, podczas importowania, więc defaultpo prostu kondensuj przypisanie zmiennej do jednego słowa kluczowego.

Mani Gandham
źródło
-3

Dla mnie jest to tylko jedna z wielu osobliwości (nacisk na idio (t)) maszynopisu, który powoduje, że ludzie wyciągają włosy i przeklinają twórców. Być może mogliby opracować bardziej zrozumiałe komunikaty o błędach.

Duży pies
źródło