gpt4 book ai didi

javascript - 状态正在返回新状态而不触及状态 REACT/REDUX

转载 作者:行者123 更新时间:2023-12-03 03:56:37 25 4
gpt4 key购买 nike

在开始发布代码之前,我将解释我想要发生的事情以及正在发生的事情。

我一整天都在研究这个问题,终于找到了一些工作。问题是我不知道它为什么有效以及这是否是最好的方法。我想要发生的是,当用户单击评论上的删除时,我希望该评论从后端的当前 post 和前端的状态中删除。

更新:我并没有真正添加足够的内容来展示我在说什么。当用户单击删除按钮时,它将在此处触发此功能:

deleteComment(comment) {
const {id} = this.props.match.params;
const {user, post, auth} = this.props;

if(!user) {
return (<div></div>);
}

if(auth) {
if(user._id === comment.author.id){
this.props.deleteComments(post, comment._id, () => {
this.props.history.push(`/posts/${post._id}`);
});
}
}
}

然后调用操作:

export function deleteComments(post, comment_id, cb) {
return function(dispatch) {
axios.delete(`${ROOT_URL}/${post._id}/comments/${comment_id}`)
.then(() => {
dispatch({
type: DELETE_COMMENTS,
payload: comment_id,
post: post
});
})
.then(() => cb())
.catch((error) => {
console.log(error);
});
}
}

我想知道的是:实际上,上面的所有代码都有效,因此它更像是一个引用。我想知道为什么在 reducer 中,当 DELETE_COMMENTS 被 switch case 捕获时,图片下面的当前状态如何更改为新状态,而没有删除我的注释。我没有明确地编辑或更改状态,那么 return (state); 如何在此处实际更改它?

详细说明我目前的状态如下:

enter image description here

正如你所看到的,我有一篇帖子,里面有评论。评论存储在一个数组中,每个评论都是具有文本、author.id、author.email 和createdAt 值的对象。现在,正如您在reducer_post中看到的那样,当操作被触发时,它会关闭DELETE_COMMENTS调度类型并且状态发生变化。

寻求帮助:action.payloadcomment._idaction.post 是当前正在查看的帖子。

import {
GET_ALL_POSTS,
GET_POST,
CREATE_POST,
DELETE_POST,
UPDATE_POST,
DELETE_COMMENTS
} from '../actions/types';
import _ from 'lodash';

export default function(state = {}, action) {
switch(action.type) {
case GET_ALL_POSTS:
return _.mapKeys(action.payload.data, '_id');
break;
case GET_POST:
return {...state, [action.payload.data._id]: action.payload.data};
break;
case DELETE_POST:
return _.omit(state, action.payload);
break;
case DELETE_COMMENTS:
let newCommentArray = _.reject(action.post.comments, {'_id': action.payload});
let newPost = action.post;
newPost.comments = newCommentArray;
return (state);
case UPDATE_POST:
let updates = {[action.payload.data._id]: action.payload.data};
return _.merge(...state, updates);
break;
default:
return state;
break;
}
}

我知道后端工作得很好,这也工作得很好。我的问题是,我只需输入 return (state); 即可更新状态。我不必做类似 return _.merge(...state, newPost); 或类似的事情。这一切工作得怎么样,不,我不只是复制一些教程然后来这里问这个只是为了弄清楚其他人是如何做到的。目前我相信魔法,所以最好能有一个解释。

既然我们在这里,这是最好的方法吗?或者这里有更好更干净的做事方式。

最佳答案

我认为您实际上是在直接改变状态,并且在组件仍在更新的意义上以某种方式摆脱它。

让我们遵循逻辑:

  1. deleteComment() 中,您引用 this.props.post。该对象可能是通过 mapStateToProps 从存储中提取的,因此它是存储中的对象引用。
  2. post 被传递给 this.props.deleteComments(post)
  3. deleteComments() 调度 ({type : DELETE_COMMENTS, post})
  4. 在reducer中,你有let newPost = action.post; newPost.comments = newCommentArray。但是,此时,newPost 仍然指向已处于存储状态的完全相同的对象。所以,你直接改变了它。

通常情况下,这种突变会导致您的组件无法重新渲染,因此我只能假设在 mapState 中提取的其他一些值也得到了正确更新,从而导致重新渲染渲染。

Structuring Reducers - Immutable Update Patterns 中所述在 Redux 文档页面中,let someVariable = anotherVariable 不会创建新的对象引用 - 它只是创建第二个指向相同对象引用的变量。正确的不可变更新需要您正在使用的每一层嵌套的副本,而不仅仅是一层。在您的情况下,您将通过 _.reject() 创建一个新数组,但不会创建 post 对象的副本。

所以,最后,你的 reducer 逻辑是不正确的,你的应用程序有点意外地工作:)

更新

回答您关于正确更新的问题:您需要创建 post 对象的副本并使用新的注释数组更新它,并且您需要复制state 对象并使用新的 post 对象更新它。根据其余代码的作用,我的猜测是这应该有效:

case DELETE_COMMENTS:
const newCommentArray = _.reject(action.post.comments, {'_id': action.payload});

const newState = {
...state,
[action.post.id] : {
...action.post,
comments : newCommentArray
}
};

return newState;

关于javascript - 状态正在返回新状态而不触及状态 REACT/REDUX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44913729/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com