如何在不更新ReactJs中的数组列表中单个项目的状态的情况下更新数组

时间:2020-06-21 23:07:47

标签: javascript arrays reactjs redux react-redux

所以我正在研究一个React项目,该项目具有与instagram相关的功能,以便提取数据(您可以将其称为feed)。

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

因此,每个项目的视觉效果必须具有“喜欢/不喜欢”按钮,“跟随/取消关注”按钮并创建评论表单。我只想更新一个项目,而当我单击一个项目上的“赞”按钮时,它将更新列表中的另一个项目。

到目前为止,从我所做的事情来看,当您单击“喜欢”按钮时,它将调度一个动作并将状态更新为isLike:true,它将用于更改“喜欢”按钮的颜色,但会影响列表中的每个项目

  1. 处理类似按钮和不同按钮的功能

       const handleLikeClick = () => {
         const data = {
           postId,
         };
         props.unlikePost(data, token);
       };
       const handleUnlikeClick = () => {
         const data = {
           postId,
         };
         props.likePost(data, token);
       };
    
    1. 视图取决于状态,取决于所调度的动作

       {isLike ? (
                 <i onClick={handleLikeClick}>
                   <img src={IconLike} alt="" />
                 </i>
               ) : (
      
      )}
    2. 处理对api的请求的函数

   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. Reducer文件

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
      };

这就是我到目前为止所拥有的,因此,一旦分派了动作并更新了isLike,它就应该更改列表中每个项目而不是列表中所有项目的like按钮的颜色。 预先感谢。

2 个答案:

答案 0 :(得分:0)

问题是您拥有redux属性isLike,而不是从后端检索帖子的状态。显然,单个布尔属性不能表示所有不同帖子的状态。如果用户刷新页面会怎样?您需要做的是将属性isLiked添加到数据本身,并在redux中拥有一系列帖子,当有人喜欢(或不喜欢)帖子时,这些帖子就会更新。

但是请记住,“喜欢”位于 user 和帖子之间,它不是帖子本身的属性。因此,后端的设置方式必须使返回的数据考虑将数据返回到的对象。因此,GET请求将需要包含用户的ID,后端将需要从多个表中提取数据以创建JSON响应。

如果您忽略后端,则至少需要将isLiked字段添加到发布数据中,将该数组保留在redux中,并在用户单击时更新该数组中的特定项。 / p>

答案 1 :(得分:0)

有一种这种模式,您可以将所有id存储在数组中,将数据存储在对象中。

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

现在,父组件将订阅allIds(仅包括键)并呈现子数组。每个孩子将从组件本身订阅自己的数据。因此,在需要时更新byId对象中的项目只会影响自身。

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