🐛 Bug Report
Using on an array a producer which first modifies a value but later on reverts it to the original one still keeps the draft marked as "modified" and therefore spawns a new array, making the output not strictly equal to the input.
To Reproduce
Execute that:
const immer = require('immer');
const original = [1];
const modified = immer.produce(original, function (array) {
array[0] = 2; // modify it
array[0] = 1; // revert it back to original value
});
console.log(modified === original); // outputs "false"
Expected behavior
From the concept of immutability, I expect conceptually equal values to be strictly equal in practice. In other words: a reference pointing to an array of value [1] should always be strictly equal to another reference pointing to an array of value [1].
I understand that using an API like immer, it is difficult to track that down across different calls to produce. e.g.
const original = [1];
const modified1 = immer.produce(original, function (array) { array[0] = 2; });
console.log(modified1 === original); // outputs "false" as expected
const modified2 = immer.produce(modified1, function (array) { array[0] = 1; });
console.log(modified2 === original); // outputs "false" while we could expect "true", since they actually have the same value ([1]), but I understand this is difficult to track down
However, I would have expected it to be possible inside the same call to produce:
const original = [1];
const attempt1 = immer.produce(original, function (array) { array[0] = 1; });
console.log(attempt1 === original); // outputs "true" as expected
const attempt2 = immer.produce(
original,
function (array) {
array[0] = 2; // marks the value as "modified"
array[0] = 1; // doesn't mark it back to "not modified"
},
function (patches) {
console.log(patches); // this outputs an empty list, and that is expected!
// This can be used as workaround outside to reassign the output of `produce` to the base value if patches list is empty,
// so that I can achieve my goal of having the same reference
}
);
console.log(attempt2 === original); // outputs "false" and that's not really expected
Link to repro
Immer sandbox - CodeSandbox (open the console).
Environment
PS: identified piece of code: immer/proxy.js at master · immerjs/immer, once modified once, no chance to check if value is back to the original. Anyways, there is markUnchanged counterpart, and with complex hierarchies I understand marking back as "not modified" could be complex though, since it doesn't necessarily means the parent is not modified anymore
🐛 Bug Report
Using on an array a producer which first modifies a value but later on reverts it to the original one still keeps the draft marked as "modified" and therefore spawns a new array, making the output not strictly equal to the input.
To Reproduce
Execute that:
Expected behavior
From the concept of immutability, I expect conceptually equal values to be strictly equal in practice. In other words: a reference pointing to an array of value
[1]should always be strictly equal to another reference pointing to an array of value[1].I understand that using an API like immer, it is difficult to track that down across different calls to
produce. e.g.However, I would have expected it to be possible inside the same call to
produce:Link to repro
Immer sandbox - CodeSandbox (open the console).
Environment
setUseProxies(true)setUseProxies(false)(ES5 only)PS: identified piece of code: immer/proxy.js at master · immerjs/immer, once modified once, no chance to check if value is back to the original. Anyways, there is
markUnchangedcounterpart, and with complex hierarchies I understand marking back as "not modified" could be complex though, since it doesn't necessarily means the parent is not modified anymore