Javascript React/redux prev状态随着下一个全州范围的变化而不断变化
当有人评论时,我想更改图像的状态,以便将新的评论添加到屏幕上。状态确实会更改,但不会调用新渲染,因为旧状态会随新状态一起更改。我尝试使用调试器,似乎第40行是旧状态更改的地方。我非常困惑,因为我使用的是Object.freeze(),而且我只使用了我创建的newState变量,甚至没有触及旧的状态。谢谢Javascript React/redux prev状态随着下一个全州范围的变化而不断变化,javascript,reactjs,redux,react-redux,state,Javascript,Reactjs,Redux,React Redux,State,当有人评论时,我想更改图像的状态,以便将新的评论添加到屏幕上。状态确实会更改,但不会调用新渲染,因为旧状态会随新状态一起更改。我尝试使用调试器,似乎第40行是旧状态更改的地方。我非常困惑,因为我使用的是Object.freeze(),而且我只使用了我创建的newState变量,甚至没有触及旧的状态。谢谢 import { RECEIVE_ALL_IMAGES, RECEIVE_ONE_IMAGE, REMOVE_IMAGE, REMOVE_IMAGES } from '../ac
import {
RECEIVE_ALL_IMAGES,
RECEIVE_ONE_IMAGE,
REMOVE_IMAGE,
REMOVE_IMAGES
} from '../actions/image_actions';
import {
RECEIVE_LIKE,
REMOVE_LIKE
} from '../actions/like_actions';
import {
RECEIVE_COMMENT,
REMOVE_COMMENT
} from '../actions/comment_actions';
const imagesReducer = (oldState = {}, action) => {
Object.freeze(oldState);
let newState = Object.assign({}, oldState);
switch(action.type){
case RECEIVE_LIKE:
newState[action.like.imageId].likerIds.push(action.like.userId);
return newState;
case REMOVE_LIKE:
newState[action.like.imageId].likerIds = newState[action.like.imageId].likerIds.filter(id => id !== action.like.userId);
return newState;
case RECEIVE_ALL_IMAGES:
return Object.assign({}, oldState, action.images);
case RECEIVE_ONE_IMAGE:
return Object.assign({}, oldState, {[action.image.id]: action.image});
case REMOVE_IMAGE:
delete newState[action.image.id];
return newState;
case REMOVE_IMAGES:
return {};
case RECEIVE_COMMENT:
if (newState[action.comment.imageId].comments) {
newState[action.comment.imageId].comments[action.comment.id] = action.comment;
} else if (newState[action.comment.imageId]) {
newState[action.comment.imageId].comments = {};
newState[action.comment.imageId].comments[action.comment.id] = action.comment;
}
return newState
case REMOVE_COMMENT:
delete newState[action.comment.imageId].comments[action.comment.id]
return newState
default:
return oldState;
}
};
export default imagesReducer;
您只需冻结和复制第一层属性,然后再将层更改为更深一层,这些属性仍然是共享的。下面是一个代码段,它显示了正在发生的事情以及更改它的一种方法,但您可能希望了解如何使用一个库,以使这一点更容易得到正确的结果:
constoldstate={
id1:{注释:{cid1:'Comment1'}},
id2:{comments:{cid2:'Comment2'}}
};
document.getElementById(“step1”).innerHTML='oldState='+JSON.stringify(oldState);
对象。冻结(旧状态);
const newState=Object.assign({},oldState);
newState.id1.comments.cid3='Comment3';
document.getElementById(“step2”).innerHTML='oldState='+JSON.stringify(oldState)+'
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)+'
newState='+JSON.stringify(newState)+'
newStateNoSideEffects='+JSON.stringify(newStateNoSideEffects)代码>
您只复制了较浅的旧状态,但您正在对象中更深的位置变异值。冻结只适用于对象本身,而不是根对象属性值的嵌套对象。谢谢提示!我搜索了一个库,找到了loadash,现在使用merge而不是Object.assign!lodash merge仍将继续,我已经添加了一个用于此目的的库(不变性助手)的示例。