Correct way to export object in es6 module - javascript

I'm trying to export an my module as an object but exporting it seems an 'anti pattern' (https://medium.com/#rauschma/note-that-default-exporting-objects-is-usually-an-anti-pattern-if-you-want-to-export-the-cf674423ac38)
So I was wondering what's the correct way to export an object and then use it as
import utils from "./utils"
`
utils.foo()
Currently I'm doing like so
/** a.js **/
function foo(){
//...
}
export {
foo
}
/** b.js **/
import * as utils from "a";
utils.foo()
is it correct like so? Do I maintain the tree-shaking feature?
thanks

If the object you want to import/export only contains some functions (as I assume due to the Utils name), you can export the functions separately as follows:
export function doStuff1() {}
export function doStuff2() {}
And import like this:
import {doStuff1, doStuff2} from "./myModule";
However, if the object you want to export holds state in addition to methods, you should stick to a simple export default myObject. Otherwise, calling the imported methods won't work as intended, since the context of the object is lost.
As an example, the following object should be exported as a whole, since the properties of the object should stay encapsulated. Only importing and calling the increment function would not mutate myObject since the context of the object cannot be provided (since it's not imported as a whole).
const myObject = {
counter: 0,
increment: function() {
this.counter++;
}
}
export default myObject;

es6 native way to do this:
// file1.es6
export const myFunc = (param) => {
doStuff(param)
}
export const otherFunc = ({ param = {} }) => {
doSomething({ ...param })
}
// file2.es6
import { otherFunc } from './file1.es6'
import * as MyLib from './file1.es6'
MyLib.myfunc(0)
MyLib.otherFunc({ who: 'Repley' })
otherFunc({ var1: { a1: 1 } })
And so on.

Related

What is the difference between React Store to global objects?

We can use something like this:
// GlobalStore.js
import { store } from 'react-easy-store'
const _store = store({a: 1})
export default _store
And use it like this:
// any file.js
import GlobalStore from 'path/to/global-store'
import { view } from 'react-easy-state'
export default view(() => {
console.log(GlobalStore.a) // 1
})
We could also create a file like this:
// GlobalStore.js
export default {
a: 1
}
and import it like this:
// any file.js
import GlobalStore from 'path/to/global-store'
export default () => {
console.log(GlobalStore.a) // 1
}
We also can add "inner methods" either in React store and either in any JS object like this:
{
...
someMethod() { // do something with the object }
}
Also, when using "regular" js object and import it from elsewhere in the app, it always be "ready" and up to date with the new defined info's, for example: if file A updates the GlobalScope, when we navigate or import file B that also imports file A, it will be up to date with the new data that file A leaved.
In addition we have Redux which is much complex than the 'react-easy-store' that I mentioned above.
So what are the differences / benefits?
Why installing a third party dependency if we can actually achieve the same thing with basic JS?

How to export inner function from (exported default) outer const block?

I have this code in file "Strings.js":
const Strings = {
getString(str) {
... // some logic
},
... // more functions
}
export default Strings;
I want to import both the whole thing (Strings) and/or just the getString function from another file like that:
import Strings, { getString } from '../../utils/Strings';
or maybe just:
import { getString } from '../../utils/Strings';
to be able to write simply getString and not Strings.getString (in multiple lines).
When I try to use it, I get the following error:
Attempted import error: 'getString' is not exported from '../../utils/Strings'.
Sorry if this question was already asked, I could not find an answer.
You should use named exports, not an object:
export function getString(str) {
… // some logic
}
… // more functions
You can then import them as a namespace object
import * as Strings from '../../utils/Strings';
… Strings.getString(…) …
or directly
import { getString } from '../../utils/Strings';
… getString(…) …
If you absolutely want/need to write import Strings from '…'; (you really shouldn't), you will need to add a default export object:
… // function declarations
export default { getString }
You either have to
function getString (str) {
}
const Strings = {
getString
}
export default Strings
export { getString }
or
const Strings = {
getStrings(str) {
}
}
const { getStrings } = String
export default Strings
export { getString }
So, there is no direct way to export an object property

How to import anonymous functions in ES6

In ES6, we can import exported modules like this:
import { Abc } from './file-1'; // here Abc is a named export
import Def from './file-2'; // here Def is the default export
But how can we import anonymous functions? Consider this code:
file-3.js:
export function() {
return 'Hello';
}
export function() {
return 'How are you doing?';
}
How can I import above two functions in another file, given that neither are they default exports nor are they named exports (anonymous functions don't have names!)?
Single anonymous function can be exported as default (default export value can be anything). Multiple anonymous functions cannot be exported from a module - so they cannot be imported, too.
export statement follows strict syntax that supports either named or default exports. This will result in syntax error:
export function() {
return 'Hello';
}
These functions should be named exports:
export const foo = function () {
return 'Hello';
}
export const bar = function () {
return 'How are you doing?';
}
So they can be imported under same names.

How can I export all functions from a file in JS?

I'm creating a unit converter, and I want to put all of the conversion functions into their own file. Using ES6 export, is there any way to export all of the functions in the file with their default names using only one line? For example:
export default all;
The functions are all just in the file, not within an object.
No, there's no wildcard export (except when you're re-exporting everything from another module, but that's not what you're asking about).
Simply put export in front of each function declaration you want exported, e.g.
export function foo() {
// ...
}
export function bar() {
// ...
}
...or of course, if you're using function expressions:
export var foo = function() {
// ...
};
export let bar = () => {
// ...
};
export const baz = value => {
// ...
};
I think there are a lot of solutions to this. And as has been answered, there's no wildcard export. But, you can 'wildcard' the import. So, I much prefer the one putting export before each of the functions you want to expose from the file:
//myfile.js
export function fn1() {...}
export function fn2() {...}
and then import it like so:
import * as MyFn from './myfile.js'
Afterwards you could use it like so:
MyFn.fn1();
MyFn.fn2();
You can also use module.exports as follows:
function myFunction(arg) {
console.debug(arg);
}
function otherFunction(arg) {
console.error(arg);
}
module.exports = {
myFunction: myFunction,
otherFunction: otherFunction,
};
Then you can import it:
import {myFunction, otherFunction} from "./Functions.js";
In my use case, I do have three reusable functions in one file.
utils/reusables.js
export const a = () => {}
export const b = () => {}
export const c = () => {}
In order to point the root folder instead of individual file names, I created a file called index.js which will comprise of all the functions that are listed in individual files.
utils/index.js
export * from './reusables'
Now, when I want to use my a function, I will have to simply import it like this
import { a } from '../utils'
Rather than calling it from its individual files
import { a } from '../utils/reusables'
You could also export them at the bottom of your script.
function cube(x) {
return x * x * x;
}
const foo = Math.PI + Math.SQRT2;
var graph = {
options: {
color:'white',
thickness:'2px'
},
draw: function() {
console.log('From graph draw function');
}
}
export { cube, foo, graph };
You can also aggregate submodules together in a parent module so that they are available to import from that module.
// In parentModule.js
export { myFunction, myVariable } from 'childModule1.js';
export { myClass } from 'childModule2.js';
// In top-level module
import { myFunction, myVariable, myClass } from 'parentModule.js'
For Node.js environment, what I did to export functions was this.
UserController.js
module.exports = {
signUp: () => {
return "user"
},
login: () => {
return "login"
}
}
UserRouter.js
const UserController = require('./UserController')
then login and signUp functions could be used inside UserRouter as UserController.signUp() and UserController.login()
I think there's a missing common solution, which is exporting in index.js file:
myModule/myFunctions.js
export const foo = () => { ... }
export const bar = () => { ... }
then in myModule/index.js
export * from "./myFunctions.js";
This way you can simply import and use it with:
import { foo, bar } from "myModule";
foo();
bar();
functions.js
function alpha(msj) {
console.log('In alpha: ' + msj);
}
function beta(msj) {
console.log('In beta: ' + msj);
}
module.exports = {
alpha,
beta
};
main.js
const functions = require('./functions');
functions.alpha('Hi');
functions.beta('Hello');
Run
node main.js
Output
In alpha: Hi
In beta: Hello
In case anyone still needs an answer to this in modern JavaScript:
const hello = () => "hello there"
const bye = () => "bye bye"
export default { hello, bye }
What I like to do is to export all functions within an object:
//File.js
export default {
testFunction1: function testFunction1(){
console.log("Hello World")
},
//a little bit cleaner
testFunction2: () => {
console.log("Nothing here")
}
}
Now you can access the functions with calling the key value of the object:
//differentFile.js
import file from 'File.js'
file.testFunction1()
//Hello World
file.testFunction2()
//Nothing here

Failing to import properties of a module

I have a module A that is like
const defaults = {
something: {...},
somethingElse : {...}
}
export { defaults as default };
And then I am importing like
import * as mod, { something } from 'moduleA';
mod is correctly an object that has the two declared properties, but { something } is undefined.
Any idea what can be the reason?
[With the module as in the question] I am importing like
import * as mod, { something } from 'moduleA';
but something is undefined
But you don't have an export with the name something in your module. There only is a default-export that contains an object. You would need to do
import mod from 'moduleA';
const { something } = mod;
I have a module A that is like
const defaults = {
something: {...},
somethingElse : {...}
}
export { defaults as default };
But you really shouldn't do that anyway. Exporting "singleton" objects that act like a namespace is an antipattern in ES6 modules. You should use named exports instead:
export const something = {...};
export const somethingElse = {...};
With this, your original attempt at importing the module would have worked.
If you want to be able to access named exports in your import, you have to export them directly:
const defaults = {
something: {...},
somethingElse : {...}
}
export {
defaults as default,
defaults.something as something,
defaults.somethingElse as somethingElse
};
Alternatively you could use destructuring for the export of something and somethingElse:
export const { something, somethingElse} = defaults;
And then import it like you did:
import * as mod, { something } from 'moduleA';
But: mod will now contain the props: defaults, something, somethingElse.
If you only wont the default (which equals your defaults):
import mod, { something } from 'moduleA';
You can learn more about the ES6 import and export syntax in Axel Rauschmayr's great blog post:
http://www.2ality.com/2014/09/es6-modules-final.html
import * as mod, { something } from 'moduleA';
The reason something is undefined is because when you: export { defaults as default }; you're exporting a member called default. When you export {apple, banana} you export a member apple and a member banana.
When you import something without specifying the members you want to import you import the member named default. When you do specify the members you wish to import, of course, you import those.
This is why although your code doesn't do what you intend, the following will:
const mod = { something: 'test'};
export { mod as default }; // same as export default mod;
and
import mod, {default as test} from './index'; // test and mod both have the same values
console.log(mod); // { something: 'test' }
console.log(test.something); // test
something is not exported from your module A, only the object defaults is.
So, to get something, you need to take it from what you imported.
import * as mod from 'moduleA';
const something = mod.something;
If you want to be able to import something like this : import {something} from 'moduleA', you will need to export it explicitely. For example:
export const something = {};
const somethingElse = {};
export default const defaults = {
something,
somethingElse
};

Categories

Resources