reactjs changing object attributes inside the state object - javascript

I get an object as response from a get.
Now I assign the object to a state var (object) like this:
this.setState({editData: response.data})
Is there a way to change the values within this object?
I thought about something like this:
this.setState({editData.[var]: [value]})
thanks

Firstly you have to remember that you should never mutate state object directly. So first you shold make a copy of state object and mutate the copy. Then set this copy as state. You can use spread syntax to achieve it:
this.setState((prevState) => ({editData: {...prevState.editData, [var]: value}}));
Here is working example showing that source object is not mutated:
let state = {
editData: {
age: 22
}
};
let age = "age";
let stateCopy = {editData: {...state.editData, [age]: 100}};
console.log(state);
console.log(stateCopy);

Related

How to copy object to new variable

Let's say I have class called Person, which have firstName, lastName, and Array of addresses fields.
And in one of my angular components I am getting Person object to do some operation on them. But I would like to create two copies of this obj. To do that I am using Object.assign. But after that when I am manipulating firstName from firstCopyPerson all other objects are changed too.
How can I assign object to new variable without making reference to orginal object, but instead just creating new separate object?
mainPerson: Person;
firstCopyPerson: Person;
secondCopyPerson: Person;
ngOnInit() {
this.mainPerson = someCache.getPerson();
this.firstCopyPerson: Object.assign({}, this.mainPerson);
this.secondCopyPerson: Object.assign({}, this.mainPerson);
}
You can add this re-usable function so you can reuse this function everytime
const copyObject = (obj) => {
let result = {};
Object.entries(obj).forEach(([key, value]) => {
result[key] = value;
});
return result;
};
// Test the function
const obj1 = {name: 'notebook', price: 100};
objCopy = copyObject(obj1);
console.log(objCopy);
You can also use this way
const obj = {name: 'laptop', price: 100};
// This is the implementation line
let objCopy = {...obj};
console.log(objCopy);
whenever you use this code you are assigning a new reference to the object and both variables assigning to the same object so when you edit one of them the other will change too. you can solve this by destructing the object for example you can try this :
let personCopy = {...person}
Object.assign would only make a shallow copy of the object, that means all attributes are assigned to the same data objects.
You may want to read about deep copies which are the safe way to go.
Fenton already posted a brilliant answer to this, take a look at option 4 in his answer:
https://stackoverflow.com/a/28152032/8341158

filter with react state not filtering values

I am stumped here and no idea why as I have filtered react state many times before but this time it is doing something unexpected.
I have a functional component that has an input. The input has an onChange event. The on change event sends e to a function called updateSocial. This function takes the param e, more specifically, e.target.name, and e.target.value, and creates an object to store in state. {inputType: e.target.name, value: e.target.value}.
The state, bandSocials is an array of these objects... If the user edits the field, the function should filter out the old value, and replace it with the new value.
Heres my code:
const updateSocial = (e) => {
//Turn the bandSocials state into a new array so that I don't change the existing state yet.
let socialsArray = Array.from(bandSocials)
//Define the input type and the value.
let inputType = e.target.name
let value = e.target.value
//Filter out the old value- This is where it is not working.
socialsArray.filter((s) => s.inputType !== inputType);
//Add in the new value
socialsArray.push({inputType, value})
//Replace the bandSocails with the new array.
setSocials((band) => {
return {
...band,
bandSocials : socialsArray,
};
});
};
Each time the onChange event is called, it adds another object and does not filter out the old object.
Unlike push, which modifies the array, filter creates a new array and returns it.
let filteredArray = socialsArray.filter( ... )

one liner to remove a n element from an object

This is related to storing manipulated objects in react, but is also a general javascript question.
In react, you usually take a current state object, and add to it like so:
setFormErrors({...formErrors, agreeToRefund: 'Some message'})
where formErrors and setFormErrors is what comes out of useState() hook.
To do a delete, you have to the more verbose:
const newFormErrors = {...formErrors};
delete newFormErrors.agreeToRefund;
setFormErrors(newFormErrors)
Which is a little tedious. Is there a more abbreviated 1 liner to do this?
In 2 statements, yes, but not 1.
const {agreeToRefund , ...newFormErrors} = formErrors;
setFormErrors(newFormErrors)
But if it were me, I'd change the user of formErrors to understand a property value of null or '' instead of removing it from state entirely.
setFormErrors({...formErrors, agreeToRefund: null})
Or you can play with map and comma operator if you do not mind:
box it in a array so you can map over it to delete what you want then pop it back.
setFormErrors([{...newFormErrors}].map(obj=> (delete obj.agreeToRefund,obj)).pop())
let formErrors={fistnam:'error',lastname:'error again'}
console.log('formErrors:',formErrors)
let newFormErrors={...formErrors, agreeToRefund: 'Some message'}
console.log('newFormErrors:',newFormErrors)
let noagreeToRefund=[{...newFormErrors}].map(obj=> (delete obj.agreeToRefund,obj)).pop()//?
console.log('noagreeToRefund:',noagreeToRefund)
One option is to create a utility function (probably exported in a util library)
function newObjWithoutProperty(obj, prop) {
const newObj = { ...obj };
delete newObj[prop];
return newObj;
}
then it becomes:
setFormErrors(newObjWithoutProperty(formErrors, 'agreeToRefund'));

issues with redux payload in reducers

I have the following code for one of the CASES in reducers
case CHART_CHANGE: {
const {method,copiedArray} = payload;
let ref = copiedArray
let swapped = bubblesort(copiedArray) //<------here
console.log(ref)
console.log(swapped)
}
}
The question is this, as you can see here I assigned the variable ref before involving the bubblesort function. But when I run the program, ref variable has the same value with the swapped variable. Why is that?
In javascript objects (arrays are objects) are assigned by reference, so copiedArray and ref are referring (pointing) to the same object. If you change the contents of the object (and your bubblesort function seems to sort in place - that is mutate/change the array internally), the changes are visible in all of the variables: copiedArray, ref and swapped.
const copiedArray = [3,2,1];
const ref = copiedArray;
const swapped = copiedArray.sort();
console.log(copiedArray);
console.log(ref);
console.log(swapped);

Best way to reference an object property

Let say I have an object with
let product =
{ id:1,
model:2
}
I can reference the id by
const productId = product.id
Or I can also do
const newProductCreated = Object.assign({}, product)
then reference by newProductCreated.id
Which would be the best way for me to reference the id?
If you are working with the Redux/'Flux' methedology, the second method makes sense, it is not how you should be using it.
Assuming you are trying to create a shallow copy of the object, you can simply do this:
const productCopy = { ...product };
// or const productCopy = Object.assign({}, product) if you can't support ES6
From there, you can make respective changes to the properties within productCopy without affecting the original product.
productCopy.model = 3;
// console.log(productCopy) prints out the modified object
// console.log(product) prints out the original object
This will be conform to the immutable update patterns.

Categories

Resources