TypeError:返回减量值时,无法读取未定义的属性“ length”

时间:2019-07-23 18:43:48

标签: reactjs redux react-redux

我有一个reducer函数,可以将相似的值减

console.log(myLikes.length - 1 )给我0,我想将其输出到组件,但是我遇到了错误。

  

TypeError:无法读取未定义的属性“ length”

这是在

上发生的

DISLIKE_POST_SUCCESS

我应该怎么做才能将值返回给组件

这是减速器

import {
  UPLOAD_IMAGE_SUCCESS,
  POST_COMMENT_SUCCESS,
  DELETE_IMAGE_FAILURE,
  FETCH_IMAGES_SUCCESS,
  DISLIKE_POST_SUCCESS,
  POST_COMMENT,
  POST_LIKE,
  POST_LIKE_SUCCESS,
  POST_LIKE_FAILURE,
  DELETE_IMAGE_SUCCESS,
} from '../actions/types';
const initialState = {
  images: [],
  likedByuser: false,
};
export default (state = initialState, action) => {
  switch (action.type) {
    case FETCH_IMAGES_SUCCESS:
      return {
        ...state,
        images: action.images,
      };
    case UPLOAD_IMAGE_SUCCESS:
      const newImage = action.data;
      return {
        images: [
          {
            id: newImage[0].id,
            user: {
              username: newImage[0].user.username,
            },
            comments: {
              comment_body: newImage[0].comments.comment_body,
            },
            image_title: newImage[0].image_title,
            img_url: newImage[0].img_url,
          },
          ...state.images, // pass the previous images,
        ],
      };
    case DELETE_IMAGE_SUCCESS:
      // console.log(action)
      return {
        ...state,
        images: state.images.filter(img => img.id !== action.data),
      };
    case DELETE_IMAGE_FAILURE:
      return {
        ...state,
        error: action.error,
      };
    case POST_LIKE:
      console.log(action);
      return {
        ...state,
      };
    case POST_LIKE_SUCCESS:
      console.log(action.data);
      const newState = { ...state }; // here I am trying to shallow  copy the existing state;
      const existingLikesOfPost = newState.images.find(image => image.id === action.data).likes;
      console.log(existingLikesOfPost)
      newState.images.find(image => image.id === action.data).likes = [...existingLikesOfPost, action.newLikeObject]; // using this approach I got some code duplication so I suggested the first approach of using **push** method of array.
      return newState;
    case DISLIKE_POST_SUCCESS:
      const likeState = { ...state.images[0].likes.length - 1 }; // here I am trying to shallow  copy the existing state;
      return likeState

    case POST_COMMENT:
      return {
        ...state,
      };
    case POST_COMMENT_SUCCESS:
      //  adds a comment to a post without having to re render.
      // console.log(action.data.commentBody);
      return {
        ...state,
        images: state.images.map((image) => {
          // appends new comment withing images redux state. only if image.id === action.id
          if (image.id === action.id) {
            return {
              ...image,
              comments: [
                ...image.comments,
                {
                  comment_body: action.data[0].comment_body,
                  user: {
                    username: action.data[0].user.username,
                  },
                },
              ],
            };
          }
          return image;
        }),
      };
    default:
      return state;
  }
};

这是我在其中调用计数值的地方

图像容器(组件)

      .......
      return (
        <Grid item sm={12} md={12} className={classes.imageGridItem}>
              .......
              {img.likes ? img.likes.length  : null}
          .......
        </Grid>
      );
    }
}
ImageContainer.propTypes = {
  postComment: PropTypes.func.isRequired,
  postLike: PropTypes.func.isRequired,
};
export default ImageContainer;

Action.js

export const dislikePostSuccess = (id, data) => ({
  type: DISLIKE_POST_SUCCESS,
  id,
  data
})

Redux Saga

export function* postLike(action) {
  try {
    const id = yield call(api.images.likePost, action.data.id);

    // yield put(postLikeSuccess(id, action.data.id));
    yield put(dislikePostSuccess(id, action.data.id))
  } catch (err) {
     console.log(err); 
  }
}

重构的DISLIKE_POST案例

case DISLIKE_POST_SUCCESS:
    return {
      ...state,
      images: state.images.map((image) => {
        // appends new comment withing images redux state. only if image.id === action.id
        if (image.id === action.data) {
          return {
            ...image,
            likes:[
              ...image.likes,
              image.likes.length - 1 // adds rather than subtract

            ]
          };
        }
        return image;
      }),
    };

原始数据结构

{
  "id": 154,
  "image_title": "iiisdd",
  "img_url": "*********",
  "created_at": "2019-07-18T19:44:49.805Z",
  "updated_at": "2019-07-18T19:44:49.805Z",
  "user_id": 1,
  "user": {
    "id": 1,
    "googleId": null,
    "username": "*******,
    "password": "$********",
    "email": "e*******",
    "created_at": "2019-06-23T18:57:17.253Z",
    "updated_at": "2019-06-23T18:57:17.253Z"
  },
  "comments": [
    {
      "id": 51,
      "comment_body": "owls life",
      "created_at": "2019-07-18T20:04:51.484Z",
      "updated_at": "2019-07-18T20:04:51.484Z",
      "user_id": 8,
      "image_id": 154,
      "user": {
        "id": 8,
        "googleId": null,
        "username": "guest",
        "password": "********u",
        "email": "*******m",
        "created_at": "2019-07-18T20:04:34.315Z",
        "updated_at": "2019-07-18T20:04:34.315Z"
      }
    },
    {
      "id": 52,
      "comment_body": "dadad",
      "created_at": "2019-07-19T20:16:40.103Z",
      "updated_at": "2019-07-19T20:16:40.103Z",
      "user_id": 1,
      "image_id": 154,
      "user": {
        "id": 1,
        "googleId": null,
        "username": "*******",
        "password": "*********",
        "email": "el***********",
        "created_at": "2019-06-23T18:57:17.253Z",
        "updated_at": "2019-06-23T18:57:17.253Z"
      }
    },
    {
      "id": 53,
      "comment_body": "test",
      "created_at": "2019-07-21T22:12:44.729Z",
      "updated_at": "2019-07-21T22:12:44.729Z",
      "user_id": 1,
      "image_id": 154,
      "user": {
        "id": 1,
        "googleId": null,
        "username": "********",
        "password": "*********",
        "email": "el********",
        "created_at": "2019-06-23T18:57:17.253Z",
        "updated_at": "2019-06-23T18:57:17.253Z"
      }
    }
  ],
  "likes": [
    {
      "id": 24,
      "user_id": 2,
      "image_id": 154,
      "created_at": "2019-07-22T19:26:27.034Z",
      "deleted_at": "2019-07-22T19:26:27.034Z",
      "restored_at": "2019-07-22T19:26:27.034Z",
      "updated_at": "2019-07-22T19:26:27.034Z"
    },
    {
      "id": 141,
      "user_id": 1,
      "image_id": 154,
      "created_at": "2019-07-23T19:57:08.178Z",
      "deleted_at": "2019-07-23T19:57:08.178Z",
      "restored_at": "2019-07-23T19:57:08.178Z",
      "updated_at": "2019-07-23T19:57:08.178Z"
    }
  ]
}

1 个答案:

答案 0 :(得分:1)

您的问题是,您没有在DISLIKE_POST_SUCCESS的{​​{1}}内部返回状态对象。实质上是将当前状态更改为数字。

相反,您应该像在其他情况下一样返回状态副本。

return myLikes.length - 1

如果要跟踪喜欢的次数,可以使用附加到状态对象的单个键进行操作。

编辑

当用户不喜欢图像时,您应同时传递like ID和image ID,以便知道要删除的图像。我会做这样的事情(未经测试,请调试/验证)。

case DISLIKE_POST_SUCCESS:
  const likeState = { ...state }; // here I am trying to shallow  copy the existing state;
  //... code here
  return likeState