I wanted to double check to make sure I understand imports enough to know if it is ok to do import {_.identity} from 'underscore' opposed to import _ from 'underscore'? That is the only use of underscore if the particular file.
Thank you for your help
Looks like you're very close!
There are a few ways to do this.
IMO the cleanest way to do this goes like this:
import { map, reduce, somethingElse } from 'underscore'
Allowing you to call those methods as so:
map(things, thing => {
...
})
The '{ map, reduce } = ...' part is es6s destructuring assignment.
See the Mozilla docs page for more details on this!
Another way would be to do:
import map from 'underscore/map'
import reduce from 'underscore/reduce'
Personally, I'm not a big fan of this since it can start being a bit more cumbersome as more methods are pulled in but it does have one slight advantage, you can name the reference as you like:
import mappy from 'underscore/map'
import reducerify from 'underscore/reduce'
Though I wouldn't advise using those names!
Import: import * as _ from 'underscore'
https://underscorejs.org/#map
Example:
_.map(things, thing => {
...
})
Related
Question
I have seen a large codebase where every file with constants looks something like this:
export const DEFAULT_ID = 0;
export const CURRENT_CODE = 'ABC123';
export default {
DEFAULT_ID,
CURRENT_CODE
};
They are using both a named as well as a default export for all constants. When it comes to how the constants are actually being imported, it seems that they are usually simply importing them as named exports:
import {CURRENT_CODE} from './whatever.consts';
Is there any use case for this practice? It’s unusual, since, normally, either a named or a default export is used, not both.
Research
I checked this question hoping to get some insight into why one would use them together in this manner, but I couldn’t find anything.
The closest thing I got to an answer was in this article. In the section “Why expose a symbol as both default and named exports?”, they provide a brief example of how this allows someone to use import {A, B} from './a' instead of needing to write something like import A, {B} from './a'. However, this explanation doesn’t make sense to me since the same syntax can be used if the constants are simply exported as named exports.
My Thoughts
The only reason I can think of is that this approach can give more flexibility when it comes to importing constants. I.e., it allows using both
import {DEFAULT_ID, CURRENT_CODE} from './whatever.consts';
let id = DEFAULT_ID, code = CURRENT_CODE;
and
import INITIALIZATION_CONSTS from './whatever.consts';
let id = INITIALIZATION_CONSTS.DEFAULT_ID, code = INITIALIZATION_CONSTS.CURRENT_CODE
for importing the constants.
Is this a valid reason for using this approach? Are there any best practices implications?
Is there any use case for this practice?
Not really. The only thing I can think of is backwards-compatibility, possibly related to how they are transpiling their code, if the module is a library used elsewhere.
The only reason I can think of is that this approach can give more flexibility when it comes to importing constants.
A default export is not necessary for that. You can easily use a namespace import with named exports only:
import * as INITIALIZATION_CONSTS from './whatever.consts';
let id = INITIALIZATION_CONSTS.DEFAULT_ID, code = INITIALIZATION_CONSTS.CURRENT_CODE
How does one import map or merge or any other function from multiple imports?
import { map } from 'lodash';
import { map } from 'rxjs/operators';
import { map } from 'ramda';
The obvious answer is to:
import { map as _map } from 'lodash';
import { map as rxMap } from 'rxjs/operators';
import { map as RMap } from 'ramda';
But this is ugly and obscures code. I consider this a hack, not a solution, but a workaround due to the limitations of static analysis
I can think of another way:
import * as _ from 'lodash';
import { map } from 'rxjs/operators';
import * as R from 'ramda';
However, the JS community frowns upon this due to tree-shaking reasons. However, I am in the belief that it is over-exaggerated, only saving 45kb.
Basically you can create your own util bundles. For example:
// utils/lodash.js
export { map, get, set } from 'lodash';
// yourScript.js
import * as _ from 'utils/lodash';
It is honestly up to what you / whoever you're working for values more. Sometimes the extra 45kb is terrible but most of the time, and especially on personal project nobody should care. And if it is going to make your programming more efficient go with whatever works best for you.
If you're using those map features for specific use cases (observables, array/object manipulation, etc.) throughout your application, it is probably best to rename the methods to reflect your application's specific use case.
I'd treat them the same as if you had three non-vendor methods called "map". If you found this in your own code, you would determine if all the methods do the same thing, and if not, rename them to be more specific about what they do.
For example, rxjs.map would become mapObservable, etc. There would be a maintenance hit enforcing your new name across your modules, but the benefit would be that there is less context switching your developers will need to do to understand what's being used and why.
This may be a heavily subjective question, as the answer is likely going to vary by team, conventions, and your application.
P.S. One ways of reducing the maintenance would be to expose these methods through a wrapper, and have your team use this wrapper for those specific functions.
I'm currently importing a few lodash functions with the following syntax:
import {cloneDeep as _cloneDeep, each as _each, size as _size} from 'lodash'
This works, but it's kind of annoying to have to specify each as variable renaming. Are there any shortcuts that would avoid this? I'd be happy to have all those methods inside an object as well, to simulate the functionality of when the entire lodash library is imported, e.g. _.cloneDeep, _.each, etc.
To clarify, I don't want to import the entire library. So I'm looking for a solution that still allows the modular importing of functions.
Since your goal is to avoid annoyance I suspect this may not be what you want but if you're very set on the consumer syntax and want individual importing for efficient packing or something you could always create an intermediary module.
This module will import the contents that you want and in your main code you can reference the intermediary module in the way you're hoping to.
As an example:
import {parse as _parse, join as _join} from 'path'
export var parse = _parse;
export var join = _join;
and in your main application,
import * as path from './custom-lib/path'
path.parse(...);
It involves an extra file which sucks, but you do only have to write it once.
I wouldn't necessarily call this a good solution, but I think this is the closest you're going to get to what you want with the current standards.
ECMA2015 has the option to import all into one object/container.
import * as _ from 'lodash'
then you can use it as before:
_.cloneDeep(), _.each(), etc...
You can import the whole lib as well as individual methods:
import _, { cloneDeep, each, isArray } from 'lodash';
_.isArray([]) // true
isArray([]) // true
When you do import x from 'y'; it will store the whole y module in the x variable.
Doing import {a, b, c} from 'y'; will just pull in the specific methods a, b, c of the module.
You can combine both types of import by just delimiting them with a comma as I did in the example.
Learn more at MDN's reference.
I had a pull request feedback below, just wondering which way is the correct way to import lodash?
You'd better do import has from 'lodash/has'.. For the earlier version
of lodash (v3) which by itself is pretty heavy, we should only import
a specidic module/function rather than importing the whole lodash
library. Not sure about the newer version (v4).
import has from 'lodash/has';
vs
import { has } from 'lodash';
Thanks
import has from 'lodash/has'; is better because lodash holds all it's functions in a single file, so rather than import the whole 'lodash' library at 100k, it's better to just import lodash's has function which is maybe 2k.
If you are using webpack 4, the following code is tree shakable.
import { has } from 'lodash-es';
The points to note;
CommonJS modules are not tree shakable so you should definitely use lodash-es, which is the Lodash library exported as ES Modules, rather than lodash (CommonJS).
lodash-es's package.json contains "sideEffects": false, which notifies webpack 4 that all the files inside the package are side effect free (see https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free).
This information is crucial for tree shaking since module bundlers do not tree shake files which possibly contain side effects even if their exported members are not used in anywhere.
Edit
As of version 1.9.0, Parcel also supports "sideEffects": false, threrefore import { has } from 'lodash-es'; is also tree shakable with Parcel.
It also supports tree shaking CommonJS modules, though it is likely tree shaking of ES Modules is more efficient than CommonJS according to my experiment.
Import specific methods inside of curly brackets
import { map, tail, times, uniq } from 'lodash';
Pros:
Only one import line(for a decent amount of functions)
More readable usage: map() instead of _.map() later in the javascript code.
Cons:
Every time we want to use a new function or stop using another - it needs to be maintained and managed
Copied from:The Correct Way to Import Lodash Libraries - A Benchmark article written by Alexander Chertkov.
You can import them as
import {concat, filter, orderBy} from 'lodash';
or as
import concat from 'lodash/concat';
import orderBy from 'lodash/orderBy';
import filter from 'lodash/filter';
the second one is much optimized than the first because it only loads the needed modules
then use like this
pendingArray: concat(
orderBy(
filter(payload, obj => obj.flag),
['flag'],
['desc'],
),
filter(payload, obj => !obj.flag),
If you are using babel, you should check out babel-plugin-lodash, it will cherry-pick the parts of lodash you are using for you, less hassle and a smaller bundle.
It has a few limitations:
You must use ES2015 imports to load Lodash
Babel < 6 & Node.js < 4 aren’t supported
Chain sequences aren’t supported. See this blog post for alternatives.
Modularized method packages aren’t supported
I just put them in their own file and export it for node and webpack:
// lodash-cherries.js
module.exports = {
defaults: require('lodash/defaults'),
isNil: require('lodash/isNil'),
isObject: require('lodash/isObject'),
isArray: require('lodash/isArray'),
isFunction: require('lodash/isFunction'),
isInteger: require('lodash/isInteger'),
isBoolean: require('lodash/isBoolean'),
keys: require('lodash/keys'),
set: require('lodash/set'),
get: require('lodash/get'),
}
I think this answer can be used in any project easily and brings the best result with less effort.
For Typescript users, use as following :
// lodash.utils.ts
export { default as get } from 'lodash/get';
export { default as isEmpty } from 'lodash/isEmpty';
export { default as isNil } from 'lodash/isNil';
...
And can be used the same way as importing lodash :
//some-code.ts
import { get } from './path/to/lodash.utils'
export static function getSomething(thing: any): any {
return get(thing, 'someSubField', 'someDefaultValue')
}
Or if you prefer to keep the _ to avoid conflicts (ex. map from rxjs vs lodash)
//some-other-code.ts
import * as _ from './path/to/lodash.utils'
export static function getSomething(thing: any): any {
return _.get(thing, 'someSubField', 'someDefaultValue')
}
UPDATE :
Seems like the right way to export is :
export * as get from 'lodash/get';
export * as isEmpty from 'lodash/isEmpty';
export * as isNil from 'lodash/isNil';
...
But there is a weird collision with #types/lodash, I've removed this type package because I would get this error :
Module '"/../project/node_modules/#types/lodash/cloneDeep"' uses
'export =' and cannot be used with 'export *'.ts(2498)
UPDATE :
After some digging, I've turned tsconfig.json feature esModuleInterop to true, and it allows me to do the following :
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import isNil from 'lodash/isNil';
...
export { get, isEmpty, isNil, ... };
Note that this affects all your imports in your projects that has been defined as import * as lib from 'lib'. Follow the documentation to be sure it's suitable for you.
import { cloneDeep, groupBy } from 'lodash';
I think this is simpler when you don't need to convert array to lodash object by using _.
const groupData = groupBy(expandedData, (x) => x.room.name);
For those who want to keep using _ , then just import them like this:
import groupBy from 'lodash/groupBy';
import filter from 'lodash/filter';
import get from 'lodash/get';
window._ = {groupBy, filter, get};
I think the more cleaner way of importing lodash is just like this:-
import _ from 'lodash'
then you can use what ever you want just by using this underscore just like this:-
_.has()
Hi I switched over to ECMAScript-6 javascript syntax a little while ago and am loving it! One thing I noticed and couldn't find a definitive answer on is using nested destructing syntax on an import. What I mean is something like this..
Lets say I have a file that looks like this.
export const SomeUtils = _.bindAll({ //lodash _
someFunc1(params){
// .... stuff here
},
someFunc2(params){
// .... stuff here
},
someFunc3(params){
// .... stuff here
}
});
// ... many more of these
I have been doing something like this to get a specific function
import {Utils} from '../some/path/to/utils';
var {someFunc2} = Utils;
To get to the point.. Is there a way to do a single line import for someFunc2? like how you can do the nested object destruction assignment with brackets? (Aka: {Utils: [{someFunc2}]}) ?
I used to do var someFunc2 = require('../some/path/to/utils').someFunc2; but I can't seem to figure out how to do it with an import statement
No, ES6 module imports do not provide a destructuring option. The only feature they have are named exports (but without nesting). They are meant to exactly replace your require(…).someFunc2 pattern.
In your specific case, I don't see any reason why you would be exporting a single object as a named export. Just use
export function someFunc1(params){
// .... stuff here
}
export function someFunc2(params){
// .... stuff here
}
export function someFunc3(params){
// .... stuff here
}
so that you then can do
import {someFunc2} from '../some/path/to/utils';
To achieve what you are looking for you need to export as default:
const Utils = _.bindAll({ //lodash _
someFunc1(params){
// .... stuff here
},
someFunc2(params){
// .... stuff here
},
someFunc3(params){
// .... stuff here
}
});
export default Utils;
You can then either import the whole thing of just what you need...
import Utils, { someFunc2 } from '../some/path/to/utils';