当有人发表评论时,我想更改图像的状态,以便将新评论添加到屏幕上。状态确实会发生变化,但它不会调用新的渲染,因为旧状态会随着新状态而变化。我尝试使用调试器,似乎第 40 行是旧状态发生变化的地方。我非常困惑,因为我正在使用 Object.freeze() 并且我也只使用我创建的 newState 变量,甚至没有触及旧状态。谢谢!
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;
最佳答案
您仅卡住并复制第一层属性,但随后更改比该层更深几个级别的层,并且这些属性仍然是共享的。下面是一个片段,显示了正在发生的情况以及更改它的一种方法,但您可能需要考虑使用一个库来更容易地做到这一点:
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
时也会遇到类似的问题。
这是一个相关问题: Why should I use immutablejs over object.freeze?
这是一个使用 immutability-helper 的示例React docs 中提到:
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);
关于javascript - React/redux 上一个状态随着下一个全州范围不断变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53992167/