Вы только замораживаете и копируете первый слой свойств, но затем вы меняете слои на несколько уровней глубже, и эти свойства все еще используются совместно.Ниже приведен фрагмент, который показывает, что происходит, и один из способов его изменения, но вы можете захотеть взглянуть на использование библиотеки, которая упрощает эту задачу:
const oldState = {
id1: { comments: { cid1: 'Comment1' } },
id2: { comments: { cid2: 'Comment2' } }
};
document.getElementById("step1").innerHTML = 'oldState = ' + JSON.stringify(oldState);
Object.freeze(oldState);
const newState = Object.assign({}, oldState);
newState.id1.comments.cid3 = 'Comment3';
document.getElementById("step2").innerHTML = 'oldState = ' + JSON.stringify(oldState) + '<br/>newState = ' + JSON.stringify(newState);
const newStateNoSideEffects = {...oldState};
newStateNoSideEffects.id2 = {...newStateNoSideEffects.id2};
newStateNoSideEffects.id2.comments = {...newStateNoSideEffects.id2.comments, cid4: 'Comment4'};
document.getElementById("step3").innerHTML = 'oldState = ' + JSON.stringify(oldState) + '<br/>newState = ' + JSON.stringify(newState) + '<br/>newStateNoSideEffects = ' + JSON.stringify(newStateNoSideEffects);
<div id="root">
<div id="step1">
</div>
<br/><br/>
<div id="step2">
</div>
<br/><br/>
<div id="step3">
</div>
</div>
У вас будет похожая проблема с likerIds.push
.
Вот связанный вопрос: Почему я должен использовать immutablejs поверхobject.freeze?
Вот пример использования immutability-helper , который упоминается в React документах :
import React from "react";
import ReactDOM from "react-dom";
import update from "immutability-helper";
function App() {
const oldState = {
id1: { comments: { cid1: "Comment1" } },
id2: { comments: { cid2: "Comment2" } }
};
const newState = update(oldState, {
id1: { comments: { $merge: { cid3: "Comment3" } } }
});
return (
<div className="App">
<div>oldState = {JSON.stringify(oldState)}</div>
<div>newState = {JSON.stringify(newState)}</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);