Perché `Export Default Const` non è valido?


351

Vedo che quanto segue va bene:

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

Tuttavia, questo non è corretto:

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

Eppure va bene:

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

Questo può essere spiegato per favore perché constnon è valido con export default? È un'aggiunta non necessaria e tutto ciò che export defaultviene dichiarato come si presume un consto tale?



1
export default Tab = connect( mapState, mapDispatch )( Tabs );dovrebbe essere export default connect( mapState, mapDispatch )( Tabs );. Stai esportando il risultato della chiamata di funzione, non la variabile Tab.
ThaJay

2
Una const o let è richiesta (e pertinente) nel modulo di esportazione, ma irrilevante nel modulo di importazione, in cui l'identificatore importato è sempre di sola lettura (non è possibile assegnarlo). Questo non spiega ancora perché la sintassi di "export default" differisce da "export" non predefinita.
Denis Howe,

Risposte:


303

constè come let, è una LexicalDeclaration ( VariableStatement, Declaration ) utilizzata per definire un identificatore nel blocco.

Stai provando a mescolarlo con la defaultparola chiave, che si aspetta che HoistableDeclaration, ClassDeclaration o AssignmentExpression la segua.

Pertanto è un SyntaxError .


Se vuoi constqualcosa devi fornire l'identificatore e non usarlo default.

exportdi per sé accetta una VariableStatement o una Dichiarazione alla sua destra.


AFAIK l'esportazione in sé non dovrebbe aggiungere nulla al tuo ambito attuale.


Quanto segue va beneexport default Tab;

Tabdiventa un'espressione di assegnazione poiché viene assegnato il nome predefinito ?

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

Qui Tab = connect( mapState, mapDispatch )( Tabs );è un AssignmentExpression .


27
La risposta è come è diventato un errore. La domanda è ancora perché? L'unico motivo che impedisce l'abuso di const in questo modo: export default const a = 1, b = 3, c = 4;
Sergey Orlov,

7
"AFAIK the export in itself should not add anything to your current scope"Questo non è così preciso, perché export const a = 1aggiunge aal tuo contesto attuale. E anche con export defaultin caso di classi, perché export default class MyClass {}aggiunge anche MyClassal tuo contesto attuale.
Ernesto,

4
@SergeyOrlov concorda sul fatto che questo spiega come questo genera un errore, ma fa poca luce sul perché sia ​​necessario. Anche se non sono sicuro che sia l'unico motivo, probabilmente dovresti pubblicarlo come una risposta separata, non un commento a questo.
Herick,

Se faccio quanto segue: let a; export default a;e quindi aggiorno la variabile a quando è già stata importata in un altro modulo, perché la variabile predefinita di esportazione non si aggiorna?
K - La tossicità in SO sta crescendo.

La mia comprensione è, in breve, è possibile scrivere const foo = function bar() {}e anche const Foo = class Bar {}, ma non const foo = const bar = 1. Lo stesso per export default, è proprio come const foo =.
zetavg

47

Puoi anche fare qualcosa del genere se vuoi esportare di default una const / let, invece di

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

Puoi fare qualcosa del genere, che non mi piace personalmente.

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

19

Se il nome del componente è spiegato nel nome del file MyComponent.js, semplicemente non nominare il componente, mantiene il codice sottile.

import React from 'react'

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

Aggiornamento : poiché questo lo etichetta come sconosciuto nella traccia dello stack, non è raccomandato


14
Non hai avuto problemi con stacktraces? Per me sta causando la visualizzazione Unknownovunque dove si trova l'esportazione predefinita senza nome
Jurosh

2
Mentre funziona, senza dubbio è qualcosa che ogni sviluppatore di reazione al di fuori dello sviluppo di applicazioni giocattolo dovrebbe sforzarsi di evitare a tutti i costi.
li x

1
@lix Non riuscivo a capire perché si dovrebbe evitare di usare questa sintassi. Potresti spiegare o condividere un link per favore? Grazie.
sudip,

3
@sudip La creazione di un componente senza nome non è utile per il modello e il rendering del componente reagire.
li x

1
Sembra comunque pulito, anche Dan Abramov suggerisce che dovremmo usare i nomi di funzione / const corretti nella dichiarazione del componente: twitter.com/dan_abramov/status/1255229440860262400 ;) "- apparirà come Anonimo nelle tracce dello stack - apparirà come Sconosciuto in DevTools - non verrà controllato dalle regole di lanugine specifiche di React - non funzionerà con alcune funzionalità come Fast Refresh "
Zoltan,

9

La risposta di Paul è quella che stai cercando. Tuttavia, in pratica, penso che potresti essere interessato allo schema che ho usato nelle mie app React + Redux.

Ecco un esempio ridotto di uno dei miei percorsi, che mostra come è possibile definire il componente ed esportarlo come predefinito con una singola istruzione:

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

(Nota: utilizzo il termine "scena" per il componente di livello superiore di qualsiasi percorso).

Spero che questo sia utile. Penso che sia molto più pulito rispetto al convenzionaleconnect( mapState, mapDispatch )( BareComponent )


Peccato che i decoratori non possano essere usati su un componente funzionale
Eric Kim,

@EricKim Bummer. Ma vale la pena ricordare che le specifiche del decoratore non sono ancora definitive. Forse i componenti funzionali non possono essere decorati usando il decoratore "legacy", ma non so se ciò sia dovuto a una limitazione del design legacy, o perché l'implementazione dei decoratori legacy è incompleta o buggy. FWIW: @connectè l'unico decoratore che uso, lo uso solo con componenti collegati a un negozio di redux, quasi ognuno di questi è un "percorso" e quasi ogni percorso dovrebbe avere uno stato (e quindi non può essere una pura funzione) .
Tom,

8

La risposta condivisa da Paul è la migliore. Per espandere di più,

Può esistere una sola esportazione predefinita per file. Considerando che possono esserci più esportazioni const. La variabile predefinita può essere importata con qualsiasi nome, mentre la variabile const può essere importata con il suo nome particolare.

var message2 = 'Sono esportato';

esportazione messaggio predefinito2;

export const message = 'Anche io sono esportato'

Per quanto riguarda le importazioni, dobbiamo importarlo in questo modo:

import {message} da './test';

o

importa il messaggio da './test';

Con la prima importazione, viene importata la variabile const mentre, con la seconda, verrà importata quella predefinita.


Adoro la tua risposta, grazie!
White159

0

default è fondamentalmente const someVariableName

Non hai bisogno di un identificatore con nome perché è l'esportazione predefinita per il file e puoi nominarlo come vuoi quando lo importi, quindi defaultè solo condensare l'assegnazione delle variabili in una singola parola chiave.


-3

Per me questa è solo una delle tante idiosincrasie (enfasi sull'idio (t)) del dattiloscritto che induce le persone a strapparsi i capelli e maledire gli sviluppatori. Forse potrebbero lavorare per trovare messaggi di errore più comprensibili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.