I want to put the data from API to Vue state. What is the quick approach to do this?
getProjectData(id) {
axios.get(`/api/project/${id}`).then((res) => {
console.log(res)
/* I don't want to manually assign the value one by one (since the name is the same, there should be a quick way */
this.formState.name = res.data.projects.name
this.formState.stage = res.data.projects.stage
this.formState.status = res.data.projects.status
this.formState.description = res.data.projects.description
this.formState.stations = res.data.projects.stations
});
},
You can use spread operator to achieve it:
this.formState = {...res.data.projects}
To point out, these properties are copied shallowly. If a property value is an object, any modification made to it will reflect in the res.data.projects object.
Related
How would one JSON.stringify() a Set?
Things that did not work in Chromium 43:
var s = new Set(['foo', 'bar']);
JSON.stringify(s); // -> "{}"
JSON.stringify(s.values()); // -> "{}"
JSON.stringify(s.keys()); // -> "{}"
I would expect to get something similar to that of a serialized array.
JSON.stringify(["foo", "bar"]); // -> "["foo","bar"]"
JSON.stringify doesn't directly work with sets because the data stored in the set is not stored as properties.
But you can convert the set to an array. Then you will be able to stringify it properly.
Any of the following will do the trick:
JSON.stringify([...s]);
JSON.stringify([...s.keys()]);
JSON.stringify([...s.values()]);
JSON.stringify(Array.from(s));
JSON.stringify(Array.from(s.keys()));
JSON.stringify(Array.from(s.values()));
You can pass a "replacer" function to JSON.stringify:
const fooBar = {
foo: new Set([1, 2, 3]),
bar: new Set([4, 5, 6])
};
JSON.stringify(
fooBar,
(_key, value) => (value instanceof Set ? [...value] : value)
);
Result:
"{"foo":[1,2,3],"bar":[4,5,6]}"
toJSON is a legacy artifact, and a better approach is to use a custom replacer, see https://github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
While all of the above work I suggest that you subclass set and add a toJSON method to make sure that it stringify's correctly. Especially if you are going to be stringifying often. I use sets in my Redux stores and needed to make sure this was never a problem.
This is a basic implementation. Naming is just to illustrate the point pick your own style.
class JSONSet extends Set {
toJSON () {
return [...this]
}
}
const set = new JSONSet([1, 2, 3])
console.log(JSON.stringify(set))
The problem with all the previous approaches is that they all convert the set into Array, which is missing the entire point of Set and indexes.
What you should do is to use an Object instead.
Either convert it with the following function or simply create it as Object instead of Set.
const mySet = new Set(['hello', 'world']);
const myObj = {};
for (let value of mySet.values()) {
myObj[value] = true;
}
Then instead of using mySet.has('hello')
Do myObj.hasOwnProperty('hello').
Then stringify it as an object without a problem.
Note:
The following method uses more memory because it needs to store the value as well as the key.
But performence wise it's still O(1) compared to Array.includes() which is O(n) and miss the point of even using a Set.
I am using React.js and I'm trying to update the state of my component when the props change. Before I explain the problem, I should mention that I have used both getDerivedStateFromProps and componentDidUpdate, the result is the same. The problem is that when I try to access the value of an element in prop, it differs whether I access the value directly or I use the object itself.
let userTickets = nextProps.support.userTickets;
// userTickets[0].messages is different from nextProps.support.userTickets[0].messages
below is the whole function code.
let userTickets = nextProps.support.userTickets;
console.log(nextProps.support.userTickets); // this contains the correct, updated value
for (let index = 0; index < userTickets.length; index++) {
let userTicket = userTickets[index];
console.log(userTicket); // this contains old incorrect value
}
Any guidance would be appreciated. Thanks.
Try to not directly assign props to variables because it may assign by reference instead of copy. Try this instead:
const userTickets = [ ...nextProps.support.userTickets ];
console.log(nextProps.support.userTickets);
userTickets.map(ticket => {
console.log(ticket);
});
Notice the 3 dot assignment of the array, this creates a new array with the values of the array that is "spread"
I am trying to update the state value but first I have loaded it in another varand after changes made on the new var it is going to setState and update the original state value. but unexpectedly changes made to the temp var already changes the component state value!
var postData = this.state.postData;
postData.likes = postData.likes + 1;
console.log(postData.likes, this.state.postData.likes);
the console.log values:
(1, 1)
(2, 2)
...
Since postData is an object, don't save it directly in another variable since that will create a reference to the one in the state, not a copy. And if it's a reference, changing one will change the other cos they're both pointing to the same object.
Make a copy of it first"
var postData = Object.assign({}, this.state.postData)
and then change it. Then when you're done, use setState({postData})
you should never ever mutate state, always use setState, and for copying object user spread notation "..."
this.setState(((prevState) => ({
postData:{
...prevState.postData,
likes: prevState.postData.likes + 1,
}
});
You can also use ES2018 spread notation like var postData = {...this.state.postData}; to clone the object and manipulate it before assigning back to state.
I've read that it is not advisable to update state directly, e.g:
this.state.array = ['element'];
But, for example, consider this state:
this.state = {
array: [],
}
updateArray = element => {
temp = this.state.array;
temp.push(element);
this.setState({array: temp});
}
Isn't this essentialy the same as the first example? We are setting temp to point to this.state.array, thus mutating it and then overwriting it with this.setState().
I've seen this example in various tutorials, Wouldn't it be 'better' to make a copy of the array?
Check out the docs here, https://reactjs.org/docs/state-and-lifecycle.html.
According to the React team. Setting the state directly will not re-render a component. You must use setState.
As far as using a temp variable when setting state, that is used when something needs to be done to 'element' before setting the state variable. As setState can be called asynchronously. It is acceptable in your case to just do
updateArray = (element) => {
this.setState({ array: [ ...this.state.array, element ] });
}
Yes, you are right it's the same thing. You should read more about pass by value and pass by reference in JS.
When we say
let x = some.array
We are copying a reference(remember copy and paste as shortcut)? Both the things actually point to the same real thing and takes no extra space.
You should instead use some JS that can do this for you.
let x = some.array.slice()
This creates real copy of the array. On modern ES2015 you can do
let x = [...some.array]
a more elegent way.
I am using console.log('errors: ' + password.get('errors')); to see what is returned from password.get('errors')); and in the console this is returned:
List [ Map { "id": "validation.password.tooLong", "defaultMessage": "La password deve avere massimo {max} caratteri", "values": Map { "max": 16 } } ]
I want to access the element "validation.password.tooLong" from this mapped array, I am unsure how exactly to do this. I am not 100% sure this is a mapped array, I am assuming it is though because of the [Map... above.
I assume that you are using immutable.js, thus to get the desired data you need to access this property via methods of these classes:
const errors = password.get('errors');
const errorId = errors.get(0).get('id');
In other answers, you got an undefined because List is an instance of class List, that haven't property 0, but have a method get that returns a value from an array, that stored in the closure. It's a special solution to prevent mutating and ensure immutability (if you want to update value, you should use set(0, value) instead of myList[0] = value, so there is no access via [0]). The same thing with the Map (Map is an immutable object, that stores key: value).
You can learn more about it here: Immutable.js docs (but I'm not sure you have exactly immutable.js, there are many similar libraries, so take a look what do you use exactly).
You can try with below code:
var response = password.get('errors');
var result = response[0]['id'];
To get the value from map you need to use get() function like
var res = password.get('errors');
var ans = res[0].get('id');