Working on react application in TypeScript.
I'm trying to understand the correct syntax for exporting a default component using as
Up till now I've used:
class HomePage extends Component<IProps, IState> {
...
}
export default HomePage
or in shortly:
export default class HomePage extends Component<IProps, IState> {
...
}
now, after adding redux support. I have something like:
class HomePage extends Component<IProps, IState> {
...
}
const mapStateToProps = (state: StoreState) => {
...
};
const mapDispatchToProps = {
...
};
export default connect(mapStateToProps, mapDispatchToProps)(HomePage);
but I can't figure it out how to add as to the connect default export
e.g something like:
// This is NOT working. I get Syntax error.
export default connect(mapStateToProps, mapDispatchToProps)(HomePage) as HomePage;
is it possible? or should I do it? it's seems that anyway the export name is HomePage (when I'm importing HomePage in other file, the IDE is automatically detects and import this file). Where is it taken from? the name of the file (HomePage.tsx)?
This is do work for me:
const connectedHomePage = connect(mapStateToProps, mapDispatchToProps)(HomePage)
export {connectedHomePage as HomePage};
but it's two lines (I prefer in one line) and it's not a default export.
so, is there a way to export default AND adding as to the statement? just so it will be clear what is the exported name?
as has 2 meanings. In ES6 modules, it can be a way to rename an import or export. In TypeScript, it is a typecast operator. I am going to assume you mean the first, specifically a way to rename an export.
Now take a look at this expression you suggested:
export default connect(mapStateToProps, mapDispatchToProps)(HomePage) as HomePage;
Do you want to export it as default or do you want to export it as HomePage? When you export default, default is the export name. Given that, does this make sense to expect it to be called HomePage? You either export something that is called default or something that is called HomePage.
This table associates different export statement forms with the expected export name and local names:
For importing, though...
If you are importing a default export, you have to explicitly name the import. Default exports will not automatically have a local name after importing. Example: import express from "express". The local name does not matter. Could as well be import banana from "express".
If you are importing a named export, by default, the local name will be the same as the exported name. Example: If you have export const x = 2, then, you should import it as import { x } from "module". You can also rename the import like this: `import { x as y } from "module".
The above tables are from the ES6 specs: http://www.ecma-international.org/ecma-262/6.0/
Related
I found many files were exported like this, but I don't understand why these were exported this way.
Are there any advantages or reasons?
index.ts
export { default } from './Something'
Something.tsx
cosnt _Something= () => {
some codes....
}
cosnt Something = memo(_Something)
export default Something
These two tsx file exist same directory.
You're looking for default export and named exports.
in export default Something case, you can use it with import Something from 'path'. So you only want to export one thing. It can be used as a namespace also. It equals export { myFunction as default };
in export { Something } case, you can use it with import { Something } from 'path'. You can export many things with names. It increases the readability. For sure, you can also import { Something as Another} from 'path'.
These two appoarches are not conflict. But only one default can be assigned.
// index.ts
export default function Something(){
}
export const CONST_A = 'A'
export const CONST_B = 'B'
// use.ts
import { default as Something, CONST_A, CONST_B} from './index.ts'
Its just a pattern, instead of importing exact paths:
import Nav from 'components/Nav.react';
import Tooltip from 'components/Tooltip.react';
Sometimes you want a merge:
import { Nav, Tooltip } from 'components';
It requires exports from index file located at the target folder ('components' in this case):
// src/components/index.ts
export * from './Nav.react';
export * from './Tooltip.react';
// Or
export { Nav } from './Nav.react'; // Has a named export
export { default as Tooltip } from './Tooltip.react'; // Has default export
See more context in other question How to intellisense alias module path in VSCode.
i have got used to using named exports as it makes life easier for refactoring. I have just started to implement redux but it seems i can't do a named export because the connect needs to map the component.
so for example
class Something extends Component { ... }
export default connect(mapStateToProps)(Something);
Would it be possible to use a named export like "Something", i can't place the export on the class as although react continues to work - the connect is not getting exported so there is no redux state
Any ideas ?
Thanks in advance
Just assign it to a const and export that like so:
class Something extends Component { ... }
export const ConnectedSomething = connect(mapStateToProps)(Something);
Then you can import it like so:
import { ConnectedSomething } from './....'
If I'm understanding correctly, then you could export your "redux connected" component via named export as follows:
/*
Declare component class, with class name differing from named export
*/
class SomethingComponent extends Component { ... };
/*
Export redux connected HOC to external modules, via named export "Something"
*/
export const Something = connect(mapStateToProps)(SomethingComponent);
I suggest using [folder]/index.ts:
export { default as SomethingComponent } from './SomethingComponent.tsx';
[folder]/SomethingComponent.tsx:
class SomethingComponent {}
export default SomethingComponent;
AnyComponent.tsx:
import { SomethingComponent } from '[folder]';
export default class SampleClass extends Component {
}
while importing this class which of the following is correct?
import sampleClass(same as class name) from '.module1'; or
import Myclass(Some custome name) from '.module1';
Your component:-
app.js
export default class App extends Component{
//
}
While importing components You should always import as it is:-
import App from "./components/app";
Since you have added redux as a tag so I might guess you arisen this question while working with reducers, if i am not wrong(really sorry if i am wrong).In case of reducers they always return some object (state) a reducer always look like this
reducer-post.js
export default function(){
//return []
}
So while importing reducers you can use any name just like this
import AnyReducer from "./reducers/reducer-post"
Since reducers are functions here so by default they are imported from it, but in the case of components, they were the class so we need to explicitly import them by name.
Using the same name is unnecessary for default exports, but becomes necessary in case of named exports.
So it's better to always use the name defined in export.
I'm new to the ES6 module system so this may sound silly.
In the React Native Starter App that uses NativeBase, can anyone explain how native-starter-kit/js/components/home/index.js can do
import myTheme from '../../themes/base-theme`;
when the file it is importing from, native-starter-kit/js/themes/base-theme.js did not have any code that export default the variable myTheme?
The 2nd file you are refering to is an entire export default.
On line 5 :
export default {
// Badge
badgeBg: '#ED1727',
badgeColor: '#fff',
...
}
So when they do import myTheme from '../../themes/base-theme; the myTheme is the variable name they chose for the imported module. In this case, the transpiler is going to look for the default export.
If they would have done import { myTheme } from '../../themes/base-theme; then there would have been an issue since it is not explicitly named in the export. Doing this is not refering to the default export but rather the one explicitly called myTheme
I am not sure I made sense, you may want to give https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/import a read
Exporting without default means it's a named export.
You can have multiple named exports in a single file.
Example 1:
export class Theme {}
Here you have to import this export using its exact name.
To use this component in other file you should do this,
import { Theme } from '../../themes/base-theme'
Example 2:
If you export as the default export as,
export default class Theme {}
Then in another file you import the default export without using the { }, like this,
import Theme from '../../themes/base-theme'
There can only be one default export per file.
Although its React's convention to export one component from a file, and to export it is as the default export.
You're free to rename the default export as you import it.
import myTheme from '../../themes/base-theme'
I'm using babel / ES6 with webpack. I'm importing the same 'actions' file - which exports a bunch functions - in two different places. At one place it returns a module, the other undefined:
actions.js
export function test() { ... }
export function test2() { ... }
App.js
import actions from './actions'
class App extends React.Component { ... }
console.log(actions); //<-------- Object{test:function,test2:function)
export default connect((state) => { ... },actions)(App);
edit
the reason App.js worked was because it was actually using import * as actions as sugested below, I just retyped it wrong in the example
NestedComponent.js
import actions from './actions'
class NestedComponent extends OtherComponent { ... }
console.log(actions); //<-------- logs undefined
export default connect((state) => { ... },actions)(NestedComponent);
Is this related to the order in which webpack defines the modules/files?
I ran into a similar issue, caused by circular dependencies. Tried to import a constant in file 'A' from file 'B' which in turn tried to import from file 'A'.
This shouldn't work in either case because you are importing the wrong values. import foo from '...' imports the default export of the module, but you don't have a default export, you only have named exports.
What you should use is
import {test, test2} from './actions';
// or
import * as actions from './actions';
Another common case where this happens is if you're testing with Jest and auto-mocking behavior is enabled. Much grief, such gotcha.