ES6 Syntax Object Short Notation and Computed Properties - ecmascript-6

I am learning react-native. I came across this syntax of ES6
First Syntax
this.state = {
refreshing: false,
};
Second Syntax
this.state = {[refreshing]: false};
Will it perform same task ? If these line of code same task then what is the difference between Object Short Notation and Computed Properties

No. They are totally different:
const state = {
refreshing: false,
};
console.log(state); // { refreshing: false }
In your second example:
const state = {[refreshing]: false};
// Error: refreshing is not defined
This is because computed properties look for a variable called refreshing within the accessible scope. For example:
const refreshing = "example";
const state = { [refreshing]: false };
console.log(state); // { example: false }
So the equivalent to your first example in computed property syntax would be:
const key = "refreshing";
const state = {[key]: false};
console.log(state); // { refreshing: false }
But you would only use this if you don't know key ahead of time.

Related

Block-scoped variable 'wizard' used before its declaration.ts(2448)

Here is the code:
let args = {
"wz_nav_style": "dots", // dots, tabs, progress
"buttons": true,
"navigation": 'all' // buttons, nav, all
};
const wizard = new wizard(args);
wizard.init();
document.addEventListener("submitWizard", function (e) {
alert("Form Submit");
});
I get the error:
Block-scoped variable 'wizard' used before its declaration.ts(2448)
How to solve this?
The constant name wizard overshadows the reference of the constructor named as the same. Changing the constant name to something other than the constructor would solve the problem.
const wiz = new wizard(args);
wiz.init();

File extension not supported:null ErrorCode:13. when loading multiple models

I'm trying to load 2 models into Autodesk's Forge Viewer.
I'm trying with the following code:
const urn1 = <urn>
const urn2 = <urn>
Autodesk.Viewing.Initializer(
options,
() => {
const viewerDiv = document.getElementById('MyViewerDiv');
viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
this.loadDoc(this.props.urns[1], true);
window.setTimeout(e => {
this.loadDoc(this.props.urns[2], false);
}, 4000);
},
);
loadDoc(urn: string, initializeAndLoad: boolean) {
Autodesk.Viewing.Document.load(urn,
(doc) => {
const viewables = Autodesk.Viewing.Document
.getSubItemsWithProperties(doc.getRootItem(), {'type': 'geometry'}, true);
if (viewables.length === 0) {
return;
}
const initialViewable = viewables[0];
const svfUrl = doc.getViewablePath(initialViewable);
const modelOptions = {
globalOffset: {x: 0, y: 0, z: 0}, // to align the models
sharedPropertyDbPath: doc.getPropertyDbPath(),
};
if (initializeAndLoad) {
viewer.start(svfUrl, modelOptions,
() => {},
() => {console.log('load model error');},
);
} else {
viewer.loadModel(urn, modelOptions,
() => {},
(e) => {
console.warn(e);
});
}
},
() => {}
);
}
The rationale behind the timeout is to load the second model using loadModel after the first model has loaded. I've also tried loading the second model from the viewer.start's onSuccess callback.
No matter what, I get the File extension not supported:null ErrorCode:13. error message (both in the console and in a popup)
I'm pretty sure the message is misleading since both urns have valid SVF derivatives (I can switch between them, whichever one is loaded first displays just fine)
NB I'm using the following version:
'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.2/viewer3D.min.js'
As a side note, I've tried using Autodesk.Viewing.ViewingApplication and selectItem. With this I'm able to load multiple models but I don't seem to be able to set modelOptions (specifically globalOffset) with this approach.
The loadModel method expects a URL with some known file extension (e.g., .svf) but you're calling it with an URN (the base64-encoded identifier of a translated document). That's why it's failing to find the file extension.
Btw. if you want to postpone the loading of the second model after the first one is loaded completely, consider using the geometry-loaded-event instead of a timeout.

redux reducer flow not inferring type

I ran into a flow error while doing essentially the basic redux-reducer example from flow docs.
Error from flow added to the code here: on the REMOVE switch case: action is not resolved to the correct type.
If i hover over payload in vscode, in the ADD case it displays it as AddAction, but on REMOVE case it is displayed as a union of all the actions, i.e. Action.
What am i missing or understanding wrong? Flow should deduct the correct type down from the Actions union to the only possible type(s) inside if and switch.
// #flow
const initialState = [];
type Item = { id: number, data: string };
type State = Item[];
type AddAction = {
type: 'ADD',
payload: Item
};
type RemoveAction = {
type: 'REMOVE',
payload: { id: number }
};
type ClearAction = {
type: 'CLEAR'
};
type Action = AddAction | RemoveAction | ClearAction;
const reducer: (State, Action) => State = (state = initialState, action) => {
switch (action.type) {
case 'ADD': {
return [...state, action.payload];
}
case 'REMOVE': {
return state.filter(t => t.id !== action.payload.id);
^ property `payload`. Property not found in
}
case 'CLEAR': {
return [];
}
default:
(action: empty);
return state;
}
};
export default reducer;
code on try flow
another try-flow repl where i do essentially the same thing and type inferring works as expected
Ok, it seems that the problem was the use of action inside Array.filter arrow function:
If i replace the REMOVE case contents with
case 'REMOVE': {
const id = action.payload.id;
return state.filter(t => t.id !== id);
}
the errors go away.
I guess flow cannot infer the type inside the arrow function. Would be interesting to know why.
edit: related question
So, flow invalidates the union refinement because it assumes filter() might be doing side effects to reducer parameter action (docs). Storing the action or payload in a const before using fixes this.

Databinding function not detecting change in array of objects

I have:
<template is="dom-repeat"
initial-count="1"
index-as="index"
items="{{uploadState}}">
<div hidden="[[getState(index)]]" class="layout vertical center-center">
and I have:
properties: {
uploadState: {
type: Array,
value: function() {
var arr = Array.apply(null, Array(1));
var newArray = arr.map(()=> {
return { value: false };
});
return newArray;
},
notify: true
},
getState: function(index) {
var uploaded = this.get(['uploadState', index]);
// use this.linksPath??
return uploaded.value;
}
And:
changeState: function(index) {
this.uploadState[index].value = true;
}
When I change this.uploadState[0].value to false the hidden="[[getState(index)]]" does not detect the change.
How would I make hidden detect the change? I read this similar issue but not sure how I would use linkPath on this.
You can't work with native arrays in Polymer with data bindings. Polymer has it's own way of mapping the array elements in memory and it won't be able to detect a change to a array of elements.
Instead, I had to use the Polymer api's to mutate the arrays..this.get and this.set. This takes some getting use to since you will need to treat array elements as paths as I did with uploadState.*.
Documentation is a little rough since since there is no api documentation for array.base()(at least that I found ....not Polymer.base()).
Solution:
See Bind to an array item
<div hidden$="{{getState(uploadState.*, index, 'value')}}">
...
uploadState: {
type: Array,
value: function() {
var arr = Array.apply(null, Array(1));
var newArray = arr.map(()=> {
return { value: false };
});
return newArray;
},
notify: true
}
},
getState: function(change, index, path) {
var uploaded = this.get(path, change.base[index]);
return uploaded;
},
changeState: function() {
this.set('uploadState.0.value', true);
}

vuejs2 reusable code in N tabs

I have 5 tabs with the same user's data. Each tab has an input to search by term. How can reuse code for fetching users and searching them in opened tab. Code is in this JSFiddle:
var listing = Vue.extend({
data: function () {
return {
query: '',
list: [],
user: '',
}
},
computed: {
computedList: function () {
var vm = this;
return this.list.filter(function (item) {
return item.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
})
}
},
created: function () {
this.loadItems();
},
methods: {
loadItems: function () {
this.list = ['mike','bill','tony'],
},
}
});
var list1 = new listing({
template: '#users-template'
});
var list2 = new listing({
template: '#users-template2'
});
Vue.component('list1', list1);
Vue.component('list2', list2)
var app = new Vue({
el: ".lists-wrappers",
});
query - string of term to search
ComputedList - array of filtered data by search term.
But getting error for "query" and "ComputedList".
[Vue warn]: Property or method "query" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in root instance).
You were really close with what you had. The reason for the query error is you were using query in what looked like, to Vue, the root instances scope. You shouldn't put templates inside of other templates. Always have them outside of it (preferably as a string in your component definition).
You can read about that a bit here: https://vuejs.org/guide/components.html#DOM-Template-Parsing-Caveats
Here's how I'd approach your situation: https://jsfiddle.net/crswll/apokjqxx/6/