Why my react state became not-immutable? - javascript

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.

Related

In Javascript, after Const array variable is declared, but each of its elements can still be modified. Any reason behind it? [duplicate]

I know that ES6 is not standardized yet, but a lot of browsers currently support const keyword in JS.
In spec, it is written that:
The value of a constant cannot change through re-assignment, and a
constant cannot be re-declared. Because of this, although it is
possible to declare a constant without initializing it, it would be
useless to do so.
and when I do something like this:
const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
I see that everything is ok: xxx is still 6 and yyy is [].
But if I do yyy.push(6); yyy.push(1); , my constant array has been changed. Right now it is [6, 1] and by the way I still can not change it with yyy = 1;.
Is this a bug, or am I missing something? I tried it in the latest chrome and FF29
The documentation states:
...constant cannot change through re-assignment
...constant cannot be re-declared
When you're adding to an array or object you're not re-assigning or re-declaring the constant, it's already declared and assigned, you're just adding to the "list" that the constant points to.
So this works fine:
const x = {};
x.foo = 'bar';
console.log(x); // {foo : 'bar'}
x.foo = 'bar2';
console.log(x); // {foo : 'bar2'}
and this:
const y = [];
y.push('foo');
console.log(y); // ['foo']
y.unshift("foo2");
console.log(y); // ['foo2', 'foo']
y.pop();
console.log(y); // ['foo2']
but neither of these:
const x = {};
x = {foo: 'bar'}; // error - re-assigning
const y = ['foo'];
const y = ['bar']; // error - re-declaring
const foo = 'bar';
foo = 'bar2'; // error - can not re-assign
var foo = 'bar3'; // error - already declared
function foo() {}; // error - already declared
This happens because your constant is actually storing a reference to the array. When you join something into your array you are not modifying your constant value, but the array it points to. The same would happen if you assigned an object to a constant and tried to modify any property of it.
If you want to freeze an array or object so it can't be modified, you can use the Object.freeze method, which is already part of ECMAScript 5.
const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]
Came through this article while searching on why I was able to update an Object even after defining it as const. So the point here is that it is not the Object directly but the attributes it contains which can be updated.
For example, my Object looks like:
const number = {
id:5,
name:'Bob'
};
The above answers correctly pointed out that it's the Object which is const and not its attribute. Hence, I will be able to update the id or name by doing:
number.name = 'John';
But, I will not be able to update the Object itself like:
number = {
id:5,
name:'John'
};
TypeError: Assignment to constant variable.
This is consistent behavior with every programming language I can think of.
Consider C - arrays are just glorified pointers. A constant array only means that the value of the pointer will not change - but in fact the data contained at that address is free to.
In javascript, you are allowed to call methods of constant objects (of course - otherwise constant objects would not serve much purpose!) These methods might have the side effect of modifying the object. Since arrays in javascript are objects, this behavior applies to them as well.
All you are assured of is that the constant will always point to the same object. The properties of the object itself are free to change.
The keyword const is a little misleading.
It does not define a constant value. It defines a constant reference to a value.
Because of this you can NOT:
Reassign a constant value
Reassign a constant array
Reassign a constant object
But you CAN:
Change a constant array
Change a constant object
I think this would give you more clarity on the issue : https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 .
Basically it boils down to the const always pointing to the same address in memory. You can change the value stored in that address but cannot change the address the const is pointing too.
The definition of const you mentioned will hold true when the const is pointing to an address that holds a primitive value . This is because you cannot assign a value to this const without changing its address (because this is how assigning primitive values work) and changing the address of a const is not allowed.
Where as if the const is pointing to non-primitive value , it is possible to edit the value of the address.
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.
In addition, an also important note:
Global constants do not become properties of the window object ...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
The value of a const can't be changed through reassignment, and it can't be redeclared.
const testData = { name:"Sandeep",lastName:"Mukherjee",company:"XYZ"}
First case
testData = {name:"hello"}
console.log(testData);//throws an Error:Assignment to constant variable
Here we are reassigning testData again
Second case
const testData = {name:"Sandeep",lastName:"Mukherjee",company:"ABC"}
console.log(testData); //throws an Error: Identifier 'testData' has already been declared
Here we are redeclaring testData again
When a variable is declared using const it means it points to some memory location the
behaviour of const is we can manipulate the value stored in that memory location but not
the memory location,when we reassign/redeclare the const variable it
does not allow to change the memory location
We can change the value of a specific key
testData.company = "Google"
console.log(testData);
//{ name: 'Sandeep', lastName: 'Mukherjee', company: 'Google' }
We can add any new key value pair to it
testData.homeTown = "NewYork"
console.log(testData)
//{name: 'Sandeep',lastName:'Mukherjee',company:'Google',homeTown: 'NewYork'}
Because in const you can change the values of an object, so the object does not actually store the assignment data but instead, it points to it.
so there is a difference between primitives and objects in Javascript.
const variable stores the address (memory address such as 0xFF2DFC) that is constant.
The constant is NOT the content at the memory.
constant is memory address ONLY
Thank you for reading.
const MY_OBJECT = {'key': 'value'};
// Attempting to overwrite the object throws an error
// Uncaught TypeError: Assignment to constant variable.
MY_OBJECT = {'OTHER_KEY': 'value'};
// However, object keys are not protected,
// so the following statement is executed without problem
MY_OBJECT.key = 'otherValue';
// Use Object.freeze() to make object immutable
// The same applies to arrays
const MY_ARRAY = [];
// It's possible to push items into the array
MY_ARRAY.push('A'); // ["A"]
// However, assigning a new array to the variable throws an error
// Uncaught TypeError: Assignment to constant variable.
MY_ARRAY = ['B'];
In your constant is saved not the object, but link to the object.
You can't change this link, because it is constant.
But object you can change.

What does "object's identity must change" mean in Angular?

I am reading this Angular doc, it says:
With any object-like expression—such as object, Array, Map, or Set—the identity of the object must change for Angular to update the class list. Updating the property without changing object identity has no effect.
So, how do I change an object't identity?
Thanks.
The wording there is slightly unfortunate. You can't really change an object's identity - the identity is that object. It's like trying to make X not X. What it means is that a new object or array needs to be created for Angular to detect it as different. For a tiny example in vanilla JS:
const isSameObject = (obj1, obj2) => obj1 === obj2;
console.log(isSameObject({}, {})); // false, different objects
const someObj = {};
const sameReferenceToSomeObj = someObj;
sameReferenceToSomeObj.newProp = 'newVal';
console.log(isSameObject(someObj, sameReferenceToSomeObj)); // true, same object
For Angular to detect a change the identity on a property, the property value must be changed to a new value, rather than having the old value mutated. The second example in the snippet above is an example of how not to do things in Angular; mutating an object doesn't change its identity (it's still the same object), so if you did that in Angular, it would see that the old object on the property is === to the new object on the property, and would not produce a visual change as a result.
Create an entirely new object instead, with the desired properties, and put that object on the component, and then Angular will be able to see that the new object is not === to the old object, and take the appropriate action as a result, eg
this.theClassList = { ...this.theClassList, newProperty: 'foo' }
and not
const newClassList = this.theClassList;
newClassList.newProperty = 'foo';
this.theClassList = newClassList;

Why does splice method works on const (constant) array in JavaScript? [duplicate]

I know that ES6 is not standardized yet, but a lot of browsers currently support const keyword in JS.
In spec, it is written that:
The value of a constant cannot change through re-assignment, and a
constant cannot be re-declared. Because of this, although it is
possible to declare a constant without initializing it, it would be
useless to do so.
and when I do something like this:
const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
I see that everything is ok: xxx is still 6 and yyy is [].
But if I do yyy.push(6); yyy.push(1); , my constant array has been changed. Right now it is [6, 1] and by the way I still can not change it with yyy = 1;.
Is this a bug, or am I missing something? I tried it in the latest chrome and FF29
The documentation states:
...constant cannot change through re-assignment
...constant cannot be re-declared
When you're adding to an array or object you're not re-assigning or re-declaring the constant, it's already declared and assigned, you're just adding to the "list" that the constant points to.
So this works fine:
const x = {};
x.foo = 'bar';
console.log(x); // {foo : 'bar'}
x.foo = 'bar2';
console.log(x); // {foo : 'bar2'}
and this:
const y = [];
y.push('foo');
console.log(y); // ['foo']
y.unshift("foo2");
console.log(y); // ['foo2', 'foo']
y.pop();
console.log(y); // ['foo2']
but neither of these:
const x = {};
x = {foo: 'bar'}; // error - re-assigning
const y = ['foo'];
const y = ['bar']; // error - re-declaring
const foo = 'bar';
foo = 'bar2'; // error - can not re-assign
var foo = 'bar3'; // error - already declared
function foo() {}; // error - already declared
This happens because your constant is actually storing a reference to the array. When you join something into your array you are not modifying your constant value, but the array it points to. The same would happen if you assigned an object to a constant and tried to modify any property of it.
If you want to freeze an array or object so it can't be modified, you can use the Object.freeze method, which is already part of ECMAScript 5.
const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]
Came through this article while searching on why I was able to update an Object even after defining it as const. So the point here is that it is not the Object directly but the attributes it contains which can be updated.
For example, my Object looks like:
const number = {
id:5,
name:'Bob'
};
The above answers correctly pointed out that it's the Object which is const and not its attribute. Hence, I will be able to update the id or name by doing:
number.name = 'John';
But, I will not be able to update the Object itself like:
number = {
id:5,
name:'John'
};
TypeError: Assignment to constant variable.
This is consistent behavior with every programming language I can think of.
Consider C - arrays are just glorified pointers. A constant array only means that the value of the pointer will not change - but in fact the data contained at that address is free to.
In javascript, you are allowed to call methods of constant objects (of course - otherwise constant objects would not serve much purpose!) These methods might have the side effect of modifying the object. Since arrays in javascript are objects, this behavior applies to them as well.
All you are assured of is that the constant will always point to the same object. The properties of the object itself are free to change.
The keyword const is a little misleading.
It does not define a constant value. It defines a constant reference to a value.
Because of this you can NOT:
Reassign a constant value
Reassign a constant array
Reassign a constant object
But you CAN:
Change a constant array
Change a constant object
I think this would give you more clarity on the issue : https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 .
Basically it boils down to the const always pointing to the same address in memory. You can change the value stored in that address but cannot change the address the const is pointing too.
The definition of const you mentioned will hold true when the const is pointing to an address that holds a primitive value . This is because you cannot assign a value to this const without changing its address (because this is how assigning primitive values work) and changing the address of a const is not allowed.
Where as if the const is pointing to non-primitive value , it is possible to edit the value of the address.
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.
In addition, an also important note:
Global constants do not become properties of the window object ...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
The value of a const can't be changed through reassignment, and it can't be redeclared.
const testData = { name:"Sandeep",lastName:"Mukherjee",company:"XYZ"}
First case
testData = {name:"hello"}
console.log(testData);//throws an Error:Assignment to constant variable
Here we are reassigning testData again
Second case
const testData = {name:"Sandeep",lastName:"Mukherjee",company:"ABC"}
console.log(testData); //throws an Error: Identifier 'testData' has already been declared
Here we are redeclaring testData again
When a variable is declared using const it means it points to some memory location the
behaviour of const is we can manipulate the value stored in that memory location but not
the memory location,when we reassign/redeclare the const variable it
does not allow to change the memory location
We can change the value of a specific key
testData.company = "Google"
console.log(testData);
//{ name: 'Sandeep', lastName: 'Mukherjee', company: 'Google' }
We can add any new key value pair to it
testData.homeTown = "NewYork"
console.log(testData)
//{name: 'Sandeep',lastName:'Mukherjee',company:'Google',homeTown: 'NewYork'}
Because in const you can change the values of an object, so the object does not actually store the assignment data but instead, it points to it.
so there is a difference between primitives and objects in Javascript.
const variable stores the address (memory address such as 0xFF2DFC) that is constant.
The constant is NOT the content at the memory.
constant is memory address ONLY
Thank you for reading.
const MY_OBJECT = {'key': 'value'};
// Attempting to overwrite the object throws an error
// Uncaught TypeError: Assignment to constant variable.
MY_OBJECT = {'OTHER_KEY': 'value'};
// However, object keys are not protected,
// so the following statement is executed without problem
MY_OBJECT.key = 'otherValue';
// Use Object.freeze() to make object immutable
// The same applies to arrays
const MY_ARRAY = [];
// It's possible to push items into the array
MY_ARRAY.push('A'); // ["A"]
// However, assigning a new array to the variable throws an error
// Uncaught TypeError: Assignment to constant variable.
MY_ARRAY = ['B'];
In your constant is saved not the object, but link to the object.
You can't change this link, because it is constant.
But object you can change.

Change a 2d array in React state [duplicate]

This question already has answers here:
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Closed 4 years ago.
I have a initial state like this:
constructor(props) {
super(props);
this.state = this.getInitialState();
this.setSqValue = this.setSqValue.bind(this);
}
getInitialState() {
return {
allSq: new Array(3).fill(new Array(3).fill(null))
};
}
Then in a method like setSqValue (called by clicking a button) when I assign a new value to a cell, strangely all other cells with any position in first dimensional and same position in second dimensional will take that value!
The second problem is that the state is changed while I didn't call any setState!
setSqValue(i, j) {
console.log(i, j);
let {allSq} = this.state;
let value = 'foo';
console.log('before', allSq);
allSq[i][j] = value;
console.log('after', allSq);
// this.setState({allSq});
}
The output in the console is this :
You can see the before and after values are same (why?!).
The state in the React developer tool:
In the chrome dev tools, objects aren't evaluated until you open them. Hover on the little icon to the right and you will see Object below was evaluated just now. . Try putting a debugger in there and I have a feeling you will see that your allSq in the before doesn't have foo in there. It seems as if everything is working correctly, you're just looking at the wrong things to see that.
Also, as another user said, .fill uses reference instead of value, so use .map instead.
In JavaScript, Arrays are a special kind of Object, and if you pass an object to fill(), it uses the same object each time. You should use map() instead, which will create a copy of the array.
allSq: Array(3).fill().map(() => Array(3).fill(null))
To prevent the state from being changed you can use the Object.freeze() method:
allSq: Object.freeze(Array(3).fill().map(() => Object.freeze(Array(3).fill(null))))
With this, the line allSq[i][j] = value; will ether throw an error (in strict mode) or silently fail (outside of strict mode).

Why can I change a constant object in javascript

I know that ES6 is not standardized yet, but a lot of browsers currently support const keyword in JS.
In spec, it is written that:
The value of a constant cannot change through re-assignment, and a
constant cannot be re-declared. Because of this, although it is
possible to declare a constant without initializing it, it would be
useless to do so.
and when I do something like this:
const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
I see that everything is ok: xxx is still 6 and yyy is [].
But if I do yyy.push(6); yyy.push(1); , my constant array has been changed. Right now it is [6, 1] and by the way I still can not change it with yyy = 1;.
Is this a bug, or am I missing something? I tried it in the latest chrome and FF29
The documentation states:
...constant cannot change through re-assignment
...constant cannot be re-declared
When you're adding to an array or object you're not re-assigning or re-declaring the constant, it's already declared and assigned, you're just adding to the "list" that the constant points to.
So this works fine:
const x = {};
x.foo = 'bar';
console.log(x); // {foo : 'bar'}
x.foo = 'bar2';
console.log(x); // {foo : 'bar2'}
and this:
const y = [];
y.push('foo');
console.log(y); // ['foo']
y.unshift("foo2");
console.log(y); // ['foo2', 'foo']
y.pop();
console.log(y); // ['foo2']
but neither of these:
const x = {};
x = {foo: 'bar'}; // error - re-assigning
const y = ['foo'];
const y = ['bar']; // error - re-declaring
const foo = 'bar';
foo = 'bar2'; // error - can not re-assign
var foo = 'bar3'; // error - already declared
function foo() {}; // error - already declared
This happens because your constant is actually storing a reference to the array. When you join something into your array you are not modifying your constant value, but the array it points to. The same would happen if you assigned an object to a constant and tried to modify any property of it.
If you want to freeze an array or object so it can't be modified, you can use the Object.freeze method, which is already part of ECMAScript 5.
const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]
Came through this article while searching on why I was able to update an Object even after defining it as const. So the point here is that it is not the Object directly but the attributes it contains which can be updated.
For example, my Object looks like:
const number = {
id:5,
name:'Bob'
};
The above answers correctly pointed out that it's the Object which is const and not its attribute. Hence, I will be able to update the id or name by doing:
number.name = 'John';
But, I will not be able to update the Object itself like:
number = {
id:5,
name:'John'
};
TypeError: Assignment to constant variable.
This is consistent behavior with every programming language I can think of.
Consider C - arrays are just glorified pointers. A constant array only means that the value of the pointer will not change - but in fact the data contained at that address is free to.
In javascript, you are allowed to call methods of constant objects (of course - otherwise constant objects would not serve much purpose!) These methods might have the side effect of modifying the object. Since arrays in javascript are objects, this behavior applies to them as well.
All you are assured of is that the constant will always point to the same object. The properties of the object itself are free to change.
The keyword const is a little misleading.
It does not define a constant value. It defines a constant reference to a value.
Because of this you can NOT:
Reassign a constant value
Reassign a constant array
Reassign a constant object
But you CAN:
Change a constant array
Change a constant object
I think this would give you more clarity on the issue : https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 .
Basically it boils down to the const always pointing to the same address in memory. You can change the value stored in that address but cannot change the address the const is pointing too.
The definition of const you mentioned will hold true when the const is pointing to an address that holds a primitive value . This is because you cannot assign a value to this const without changing its address (because this is how assigning primitive values work) and changing the address of a const is not allowed.
Where as if the const is pointing to non-primitive value , it is possible to edit the value of the address.
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.
In addition, an also important note:
Global constants do not become properties of the window object ...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
The value of a const can't be changed through reassignment, and it can't be redeclared.
const testData = { name:"Sandeep",lastName:"Mukherjee",company:"XYZ"}
First case
testData = {name:"hello"}
console.log(testData);//throws an Error:Assignment to constant variable
Here we are reassigning testData again
Second case
const testData = {name:"Sandeep",lastName:"Mukherjee",company:"ABC"}
console.log(testData); //throws an Error: Identifier 'testData' has already been declared
Here we are redeclaring testData again
When a variable is declared using const it means it points to some memory location the
behaviour of const is we can manipulate the value stored in that memory location but not
the memory location,when we reassign/redeclare the const variable it
does not allow to change the memory location
We can change the value of a specific key
testData.company = "Google"
console.log(testData);
//{ name: 'Sandeep', lastName: 'Mukherjee', company: 'Google' }
We can add any new key value pair to it
testData.homeTown = "NewYork"
console.log(testData)
//{name: 'Sandeep',lastName:'Mukherjee',company:'Google',homeTown: 'NewYork'}
Because in const you can change the values of an object, so the object does not actually store the assignment data but instead, it points to it.
so there is a difference between primitives and objects in Javascript.
const variable stores the address (memory address such as 0xFF2DFC) that is constant.
The constant is NOT the content at the memory.
constant is memory address ONLY
Thank you for reading.
const MY_OBJECT = {'key': 'value'};
// Attempting to overwrite the object throws an error
// Uncaught TypeError: Assignment to constant variable.
MY_OBJECT = {'OTHER_KEY': 'value'};
// However, object keys are not protected,
// so the following statement is executed without problem
MY_OBJECT.key = 'otherValue';
// Use Object.freeze() to make object immutable
// The same applies to arrays
const MY_ARRAY = [];
// It's possible to push items into the array
MY_ARRAY.push('A'); // ["A"]
// However, assigning a new array to the variable throws an error
// Uncaught TypeError: Assignment to constant variable.
MY_ARRAY = ['B'];
In your constant is saved not the object, but link to the object.
You can't change this link, because it is constant.
But object you can change.

Categories

Resources