简体   繁体   English

如何更新数组列表中单个项目的 state 而不更新 ReactJs 中的数组中的每个列表

[英]How to update the state of single items in a list of array without updating every list in the array in ReactJs

So I am working on a React project which has the feature related to that of instagram such that a data is fetched(you can call it feeds).因此,我正在开发一个 React 项目,该项目具有与 instagram 相关的功能,以便获取数据(您可以将其称为提要)。

const feeds = [{
  postId: 1,
  body: "My first post,
  commentList: [{
    commentId: 1,
    comment: "I love this post"
  }],
  isFollowing: true,
  likers: [1]
}, ]

So the visual of each item must have a like/unlike button, follow/unfollow button and create of comment form.所以每个项目的视觉必须有一个喜欢/不喜欢按钮,关注/取消关注按钮和评论表单的创建。 I want only the item to be updated instead when i click on the like button on one item it updates other item in the list.我只希望更新该项目,而不是当我单击一个项目上的“赞”按钮时,它会更新列表中的其他项目。

From what i have done so far, when you click the like button, it dispatch an action and update the state to isLike: true which will be used to change the color of the like button but its affecting every item in the list从我到目前为止所做的事情来看,当您单击赞按钮时,它会调度一个动作并将 state 更新为 isLike: true ,这将用于更改赞按钮的颜色,但它会影响列表中的每个项目

  1. Function that handle the like and unlike button Function 处理类似和不一样的按钮

     const handleLikeClick = () => { const data = { postId, }; props.unlikePost(data, token); }; const handleUnlikeClick = () => { const data = { postId, }; props.likePost(data, token); };
    1. The view depending on the state depending on the action dispatched视图取决于 state 取决于调度的操作

       {isLike? ( <i onClick={handleLikeClick}> <img src={IconLike} alt="" /> </i> ): (
      )} )}
    2. The function that handle the request to the api处理对 api 的请求的 function

 export const likePost = (data) => async ( dispatch ) => { dispatch(likePostSuccess()) await axios.post(url, data).then((response) => { dispatch(likePostSuccess()) }).catch(({ err }) => { dispatch(likePostFailure()); }); }; export const unlikePost = (data) => async ( dispatch ) => { dispatch(unlikePostSuccess()) await axios.delete(url,{ data: { postId: data } }).then((response) => { dispatch(unlikePostSuccess()) }).catch(({ err }) => { dispatch(unlikePostFailure()); }); };

  1. The reducer file减速器文件

 const initialState = { isLike: false, } case Actions.LIKE_POST_SUCCESSFUL: return {...state, loading: false, isLike: true, }; case Actions.LIKE_POST_FAILURE: return {...state, loading: false, isLike: false }; case Actions.UNLIKE_POST_SUCCESSFUL: return {...state, loading: false, isLike: false, }; case Actions.UNLIKE_POST_FAILURE: return {...state, loading: false, isLike: true };

So thats what i have so far so once the action is dispatched and the isLike is updated it should change the color of the like button of each item in the list instead of everything in the list.所以这就是我到目前为止所拥有的,一旦动作被调度并且isLike被更新,它应该改变列表中每个项目的like按钮的颜色,而不是列表中的所有内容。 Thanks in advance.提前致谢。

The problem is that you have a redux property isLike rather than retrieving the status of the post from the backend.问题是您有一个 redux 属性isLike而不是从后端检索帖子的状态。 Clearly, a single boolean property cannot represent the state of all the different posts.显然,单个 boolean 属性不能代表所有不同帖子的 state。 And what happens if the user refreshes the page?如果用户刷新页面会发生什么? What you need to do is add the property isLiked to the data itself, and have an array of posts in redux which gets updated when someone likes (or unlikes) a post.您需要做的是将属性 isLiked 添加到数据本身,并在 redux 中有一组帖子,当有人喜欢(或不喜欢)帖子时会更新。

However remember that a 'like' is between a user and a post, it is not a property of the post itself.但是请记住,“喜欢”是在用户和帖子之间,它不是帖子本身的属性。 Therefore, the backend would need to be set up in such a way that the data it returns takes into account who it is returning the data to.因此,后端需要以这样一种方式进行设置,即它返回的数据考虑到它将数据返回给 So the GET request would need to include the user's ID, and the backend would need to pull data from more than one table to create the JSON response.因此 GET 请求需要包含用户 ID,后端需要从多个表中提取数据以创建 JSON 响应。

If you disregard the backend, at the very least you need to add the isLiked field to the post data, keep that array in redux, and update the specific item in the array when the user click like.如果不考虑后端,至少需要在post数据中添加isLiked字段,将该数组保存在redux中,并在用户点赞时更新数组中的特定项。

There is a this pattern where you store all ids in an array and data in an object.有一种这种模式,您可以将所有 id 存储在一个数组中,并将数据存储在 object 中。

reduxStore: {
 allIds: ['a', 'b', 'c', 'd'], // keys
 byId: {
   a: {isLike: true, loading: false }, 
   b: {isLike: true, loading: false}, 
   c: {isLike: false, loading: true}
}

Now the parent component will subscribe to the allIds (includes keys only) and renders array of child.现在父组件将订阅 allIds(仅包括键)并呈现子数组。 And each child will subscribe to its own data from component itself.每个孩子都会从组件本身订阅自己的数据。 So, updating items in byId object when you need, will affect only itself.因此,在需要时更新 byId object 中的项目只会影响其自身。

Ref: https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#organizing-normalized-data-in-state参考: https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#organizing-normalized-data-in-state

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM