Update state using function .map() is mutated state? - javascript

I'm still new to react and I still don't really understand about mutated the state.
I have seen many posts about this but I do not understand how the mutation process happened so I think it is necessary to ask this.
First i need to know is this called mutated state?
this.setState(prevState=>({
colors:this.state.colors.map((c,i)=>{
return{
original_color:c.original_color,
hex_color:c.hex_color,
isActive:false
}
})
}))
OR
let newData = this.state.colors.map((c,i)=>{
return{
original_color:c.original_color,
hex_color:c.hex_color,
isActive:false
}
})
this.setState({
colors: newData
})
in this case i just want to set all of this value isActive to false
Last
i want to set this value to empty
this.setState({
colors:[]
})

Since .map() returns a new array as a result, using it is safe and is not considered a mutation.
Basically, anything that doesn't change the original state or any direct references to it, is not considered a mutation.

Your state is not mutated in any case. .map() returns a new array. Your state is only mutated when you directly assign it to another value without calling .setState() like so:
this.state.value = anotherValue;
Or:
this.state.value.push(anotherValue)

Related

Initial useState - map array inside useState

Hello everyone i have a qeustion about good practices, it is fine to initialize state with map in condition like this?:
const [items, setItems] = useState(
someArray ? someArray .map(item => ({ ...item, isActive: false })) : [],
);
Yes it's ok to do, but there is an improvement that you should add. At the moment, your mapping operation is going to occur on each rerender of your function if someArray is truthy. useState() will ignore anything its passed after the first initial render, so those additional .map() operations are wasted. To avoid doing those, you can pass a state initializer function into useState() which only runs on the initial render, avoiding all the unnecessary calls to .map() for any future rerenders of your component:
const [items, setItems] = useState(() =>
someArray ? someArray.map(item => ({ ...item, isActive: false })) : [],
);
You should also be aware that useState() only uses the value it's passed on the first render, so if someArray changes in subsequent rerenders, your items will not change as it will still hold the array it was initially passed when your component was first initialised. To change items, you would need to call setItems() instead. Alternatively, you may not need to use state at all if items needs to update on each render as someArray change and instead create a regular variable that you assign the result of calling .map(), which you can make more efficient by using useMemo().
Lastly, I would also consider using Array.isArray() as your ternary condition, as not all truthy values have a .map() method.

Most efficient way to mutate an item in array of objects? [VUEX]

I read the official Vuex example of how to mutate the state of element in array of objects data.
editTodo (state, { todo, text = todo.text, done = todo.done }) {
const index = state.todos.indexOf(todo)
state.todos.splice(index, 1, {
...todo,
text,
done
})
}
It seems a bit an overkill to find the index first (first loop), perform a splice and perform a copy with spread operator ...todo (would it be considered a second loop?).
Going by the docs:
When adding new properties to an Object, you should either:
Use Vue.set(obj, 'newProp', 123), or Replace that Object with a fresh one. For example, using the object spread syntax: state.obj = { ...state.obj, newProp: 123 }
There are only two ways to set / update properties to object.
In bigger data scenario that is causing some performance issues. Is there any better (more efficient) way to update an element in array of objects?

react native setState with array

Is there a way I could setState with arrays?
this.state={
numberOne:'',
numberTwo:'',
numberThree:'',
}
this.setState({numberOne:1})
this.setState({numberTwo:2})
this.setState({numberThree:3})
The code above will work but the code below wouldn't.
this.state={
numbers:['','','']
}
this.setState({numbers[0]:0})
this.setState({numbers[1]:1})
this.setState({numbers[1]:1})
How to I setState with arrays?
You can do it as follows:
this.setState({ numbers: [1, 2, 3] })
Or if you want to edit a specific array index, then you have to create a new copy of the array, without mutating the state:
const copied = [...this.state.numbers]
copied[0] = 1
this.setState({ numbers: copied })
Keep in mind that the copying can be done by value or reference, according to the array values types.
For booleans, strings, numbers array values it's is done by value (deep copying) and mutating the copied array values won't affect the origin one's values. So if this is your case - then you should not be worried about.
For objects array values - the copying is done by reference (shallow copying) and you have to be careful to not mutate the original array incidentally. You can read more about the array copying here.
In short: Whatever approach you take, always make sure you don't mutate the origin (state) array.
That syntax makes no sense. And you can't mutate the state directly. For changing individual array elements or object properties, you need to copy that state property first, modify that value, then replace the entire property. E.g:
// Initial state in constructor
this.state = { numbers: [1,2,3] };
Then to change it somewhere:
let newNumbers = this.state.numbers.slice(0); // makes copy of the array
newNumbers[1] = 5;
this.setState({numbers: newNumbers});
and then you state will be { numbers: [1,5,3] }

Why my react state became not-immutable?

As I remember in past I could not update react-state manualy.
Now, I don't know why, I can do it.
My case:
and the property is changed here!It works! Why?
P.s: I use react16.02
the state does mutate in react. and u should be very careful that u don't override it like that or you will encounter unexpected result. it is always best to copy your state into another object, then change its properties as u like and after you are done use set state to set set your object state as copied object.
you can use Object.Assign or spread operator for this. spread operator is easier when you are using Arrays.
this.state = {
myObj : {propA: "A" , propB: "B"};
}
then at some point you want to change it
let myObj = this.state.myObj;
let copyMyObj = {...myObj};
copyMyObj.propA = "C";
this.setState({
myObj: copyMyObj
});
In javascript objects are mutable.
For example if
var a = {"something": 1}
and if you assign it to another variable b and if you change its value, the value of object a is also changed
var b = a;
b.something = 2;
console.log(b);
console.log(a);
//output {"something": 2}
both will print {"something": 2}. The value in a is also changed.
Similarly in your code you are directly assigning the state value in line number 61 and mutating it in line number 62.
So better way is to use
let newOptions = {...this.state.newOptions };
or
let newOptions = Object.assign({},this.state.newOptions}
This will create new object.
React state is mutable, so you can update react state directly. But it is recommended not to mutate react state due to multiple reasons. One of the reasons is, if you do this.state.count = 3, react DOM will behave in an unpredictable manner such as overwriting data and not re-rendering. Performance tuning is another reason.
React on calling setState() will call the render method in some near future which will cause the DOM to be updated with new values.

modifiying nested redux state without mutating

Am i Mutating redux state with this function ?
function addDefinition(object, payload) {
var newObject = Object.assign({}, object);
if(!newObject[payload.guid]){
newObject[payload.guid] = [];
}
newObject[payload.guid].push(payload);
return newObject;
}
I want to create structure to hold data related to different part of application.
Yes, that .push() statement is mutating in the later calls. In the first call, the array is newly created, so it doesn't qualify as a mutation. In a later call, you've created a new object but copied the existing array reference, so .push() mutates the existing array.
Yes. See markerikson's answer. Keep in mind you could avoid this with the spread operator.
const INITIAL_STATE = {
guid: []
}
function addDefinition(state = INITIAL_STATE, payload) {
return {...state, guid: [...state.guid, payload]};
}
In addition you could avoid the if statement with initial state.

Categories

Resources