Object destructuring default using other destructured values - ecmascript-6

The follow works in node v8.11.4 and in babel transpiled JavaScript running on chrome
const myFunc = ({
aryOfObjs,
combinedObj = Object.assign({}, ...aryOfObjs),
}) => console.log(combinedObj);
myFunc({
aryOfObjs: [
{ foo: 'bar'},
{ biz: 'baz' },
]
}); // => { foo: 'bar', biz: 'baz' }
In EMACScript 2015 is this guaranteed to work as shown above?
I know node and babel aren't 100% EMACScript 2015 complaint but I believe they both implement the object destructuring spec I can't find anything explicit on mdn that says this is supported nor on the official ECMAScript 2015 spec

Yes, this is valid ES2015 code. aryOfObjs is a variable introduced into the function scope, and Object.assign({}, ...aryOfObjs) is an expression evaluated in that scope so it can access any of those variables. The only time this would be an error is if they were accessed out of order, like
const myFunc = ({
combindedObj = Object.assign({}, ...aryOfObjs),
aryOfObjs,
}) => console.log(combindedObj);
which would throw an error because aryOfObjs has not been initialized yet.

Related

React Native - make dummy db get real data from api

I am quite new to React Native and JS and have recently purchased a React Native template which has a Dummy DB.
Ideally Id like it to pull data from an external JSON (api) which is being generated from a PHP website we already have running.
Here is the Dummy data file:
import {
DoctorModel,
TreatmentModel,
CampaignModel,
EventModel
} from "../models";
export const doctorsList: DoctorModel[] = [ { ##JSON HERE## } ];
export const treatmentsList: TreatmentModel[] = [ { ##JSON HERE## } ];
export const campaignList: CampaignModel[] = [ { ##JSON HERE## } ];
export const eventList: EventModel[] = [ { ##JSON HERE## } ];
I want it to export as the same values as above so it will work seamlessly with the current app configuration.
I have tried the following...
export const doctorsList: DoctorModel[] = () =>
fetch(' ##LINK TO API## ')
.then((response) => response.json());
But got this error:
Type '() => Promise<any>' is missing the following properties from type 'DoctorModel[]': pop, push, concat, join, and 27 more.
I have looked all over here and other platforms for a solution but cant find anything.
Again the ideal outcome would for it to work exactly how it would if I manually typed the JSON in as seen in the first code snippet.
Any help is much appreciated, still trying to wrap my head around React! :)
This doesn’t look like a react problem, but a typescript one. Typescript does a type inference from your return value to check and see if it matches what you’ve stated.
In short: you’ve just declared your types wrong.
The function doesn’t return a DoctorModel[] it’s returning Promise<DoctorModel[]>
export const doctorsList: Promise<DoctorModel[]> = () =>
fetch(' ##LINK TO API## ')
.then((response) => response.json() as DoctorsModel[]);
So changing that line ought to make your typescript compiler chooch again!

Rest-spread not being transpiled when targeting edge with NextJS

I am trying to transpile my ES6 code via Babel, I am using the next/babel preset along with preset-env and I'm using the browsers: defaults target.
The NextJS preset comes with #babel/plugin-proposal-object-rest-spread in its plugins array, I'm wondering why I am getting an error when testing on edge that says Expected identifier, string or number, and when looking in the compiled JS for the error, I see it happens when {...t} occurs.
Here is my babel.config.js:
module.exports = {
presets: [
[
'next/babel',
{
'#babel/preset-env': {
targets: {
browsers: 'defaults'
},
useBuiltIns: 'usage'
}
}
]
],
plugins: [
'#babel/plugin-proposal-optional-chaining',
'#babel/plugin-proposal-nullish-coalescing-operator',
['styled-components', { ssr: true, displayName: true, preprocess: false }],
[
'module-resolver',
{
root: ['.', './src']
}
]
],
env: {
development: {
compact: false
}
}
};
Any help on this would be greatly appreciated!
In the end my problem was related to a package that was not being transpiled by babel. My solution was to use NextJS' next-transpile-modules plugin to get babel to transpile the package code into something that would work on the browsers I need.
Here's an example of my NextJS webpack config with the package I need transpiled specified:
const withTM = require('next-transpile-modules');
module.exports = withTM({
transpileModules: ['swipe-listener']
});
SCRIPT1028: Expected identifier, string or number error can occur in 2 situations.
(1) This error get trigger if you are using trailing comma after your last property in a JavaScript object.
Example:
var message = {
title: 'Login Unsuccessful',
};
(2) This error get trigger if you are using a JavaScript reserved word as a property name.
Example:
var message = {
class: 'error'
};
solution is to pass the class property value as a string. You will need to use bracket notation, however, to call the property in your script.
Reference:
ERROR : SCRIPT1028: Expected identifier, string or number

Vuex mutation: deconstruct state parameter using ES6 syntax (using quasar framework)

I have two different syntaxes. I can access my getters and my actions using mapGetters() and mapActions(). The first one doesn't deconstruct the state parameter and works. The second one does deconstruct the state but the mutation doesn't mutate the state while the getter can access the state and the action has no problem deconstructing the context.
I don't understand why.
Do I misuse ES6 / vuejs / vuex / quasar ?
Vue.use(Vuex)
export default new Vuex.Store({
state: {
counter1: 0,
counter2: 0
},
getters: {
counter1: state => state.counter1,
counter2: ({ counter2 }) => counter2
},
mutations: {
increment1: state => state.counter1++,
increment2: ({ counter2 }) => counter2++
},
actions: {
increment1: context => context.commit('increment1'),
increment2: ({ commit }) => commit('increment2')
}
})
A friend of mine gave me the answer. I misused ES6.
{ counter2 } doesn't reference state.counter2, but makes a copy of it.
It makes sense that I can't change state.counter2 when changing counter2.

Need this vue-router function translated to ecma script 2015

I dont get the following function translated to ecmascript 2015
route: {
data: function () {
return this.$http.get('/api/posts?sort=title&order=1').then(
posts=>{this.table.posts = posts.data}
);
}
},
because this isnt refering to the window object I get the
[vue-router] Uncaught error during transition: be.js:3660:7
TypeError: undefined has no properties[Learn More]be.js:16572:13
You can use certain features such as shorthand method names and slightly more compact arrow functions to make it looks more ES2015, but it won't change the functionality:
route: {
data() {
return this.$http
.get('/api/posts?sort=title&order=1')
.then(posts => { this.table.posts = posts.data });
}
},
You couldn't replace the data hook function with an arrow functions, because this would refer to the wrong context (either to window or undefined), as its this would be defined by its surrounding lexical scope and could not be overriden.

How to check if object is Immutable?

Immutable object can be an instance of:
Immutable.List
Immutable.Map
Immutable.OrderedMap
Immutable.Set
Immutable.OrderedSet
Immutable.Stack
There is an open ticket to improve the API which is on the roadmap for 4.0. Until this is implemented, I suggest you use Immutable.Iterable.isIterable() (docs).
Using instanceof is not reliable (e. g. returns false when different modules use different copies of Immutable.js)
I have learned that using instanceof to determine wether object is Immutable is unsafe:
Module A:
var Immutable = require('immutable');
module.exports = Immutable.Map({foo: "bar});
Module B:
var Immutable = require('immutable');
var moduleA = require('moduleA');
moduleA instanceof Immutable.Map // will return false
Immutable.js API defines the following methods to check if object is an instance of Immutable:
Map.isMap()
List.isList()
Stack.isStack()
OrderedMap.isOrderedMap()
Set.isSet()
OrderedSet.isOrderedSet()
and
Iterable.isIterable()
The latter checks if:
True if an Iterable, or any of its subclasses.
List, Stack, Map, OrderedMap, Set and OrderedSet are all subclasses of Iterable.
Immutable.js has isImmutable() function since v4.0.0-rc.1:
import { isImmutable, Map, List, Stack } from 'immutable';
isImmutable([]); // false
isImmutable({}); // false
isImmutable(Map()); // true
isImmutable(List()); // true
isImmutable(Stack()); // true
isImmutable(Map().asMutable()); // false
If you use one of the previous versions, you can check if object is Immutable this way:
Immutable.Iterable.isIterable(YOUR_ENTITY)
because all immutables inherit from the Iterable object
And this way you can get to know what type of Immutable Iterable variable is:
const obj0 = 'xxx';
const obj1 = Immutable.fromJS({x: 'XXX', z: 'ZZZ'});
const obj2 = Immutable.fromJS([ {x: 'XXX'}, {z: 'ZZZ'}]);
const types = ['List', 'Stack', 'Map', 'OrderedMap', 'Set', 'OrderedSet'];
const type0 = types.find(currType => Immutable[currType][`is${currType}`](obj0));
const type1 = types.find(currType => Immutable[currType][`is${currType}`](obj1));
const type2 = types.find(currType => Immutable[currType][`is${currType}`](obj2));
console.log(`Obj0 is: ${type0}`); // Obj0 is: undefined
console.log(`Obj1 is: ${type1}`); // Obj1 is: Map
console.log(`Obj2 is: ${type2}`); // Obj2 is: List
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
Checking specific types will generally cause more work later on. Usually I would wait to lock types in by checking for Map or List, but...
My motivation here is mostly that my call .get of undefined poops itself really hard, and initializing properly all over the place helps, but doesn't catch all edge cases. I just want the data or undefined without any breakage. Specific type checking causes me to do more work later if I want it to make changes.
This looser version solves many more edge cases(most if not all extend type Iterable which has .get, and all data is eventually gotten) than a specific type check does(which usually only saves you when you try to update on the wrong type etc).
/* getValid: Checks for valid ImmutableJS type Iterable
returns valid Iterable, valid Iterable child data, or undefined
Iterable.isIterable(maybeIterable) && maybeIterable.get(['data', key], Map()), becomes
getValid(maybeIterable, ['data', key], Map())
But wait! There's more! As a result:
getValid(maybeIterable) returns the maybeIterable or undefined
and we can still say getValid(maybeIterable, null, Map()) returns the maybeIterable or Map() */
export const getValid = (maybeIterable, path, getInstead) =>
Iterable.isIterable(maybeIterable) && path
? ((typeof path === 'object' && maybeIterable.getIn(path, getInstead)) || maybeIterable.get(path, getInstead))
: Iterable.isIterable(maybeIterable) && maybeIterable || getInstead;
//Here is an untested version that a friend requested. It is slightly easier to grok.
export const getValid = (maybeIterable, path, getInstead) => {
if(valid(maybeIterable)) { // Check if it is valid
if(path) { // Check if it has a key
if(typeof path === 'object') { // Check if it is an 'array'
return maybeIterable.getIn(path, getInstead) // Get your stuff
} else {
maybeIterable.get(path, getInstead) // Get your stuff
}
} else {
return maybeIterable || getInstead; // No key? just return the valid Iterable
}
} else {
return undefined; // Not valid, return undefined, perhaps should return false here
}
}
Just give me what I am asking for or tell me no. Don't explode. I believe underscore does something similar also.
This may work in some cases:
typeof object.toJS === 'function'
You can use this ducktyping method if you check immutable vs plain objects (json), for example.