-
카테고리
-
세부 분야
풀스택
-
해결 여부
미해결
post 추가 시 오류
23.10.30 22:43 작성 조회수 149
0
안녕하세요 제로초님
다름이 아니라 로그인 후 포스트를 추가할 때 에러가 발생하는데
혼자 해결하려고 노력해봤지만 해결을 아직 하지 못하여 질문드립니다.
reducers/post.js
import shortId from "shortid";
import { produce } from "immer";
import faker from "faker";
export const initialValue = {
mainPosts: [],
//이미지업로드 할떄 이미지경로들이 여기 들어간다.
imagePaths: [],
hasMorePost: true, //true면 가져올 시도를 해라. (스크롤 했을 때)
loadPostsLoading: false,
loadPostsDone: false,
loadPostsError: null,
//게시글 추가가 완료되었을때 TRue
addPostLoading: false,
addPostDone: false,
addPostError: null,
removePostLoading: false,
removePostDone: false,
removePostError: null,
addCommentLoading: false,
addCommentDone: false,
addCommentError: null,
};
//가짜 데이터
export const generateDummyPost = (number) =>
Array(number)
.fill()
.map(() => ({
id: shortId.generate(),
User: {
id: shortId.generate(),
nickname: faker.name.findName(),
},
content: faker.lorem.paragraph(), //아무 문장,
Images: [
{
src: "https://image.utoimage.com/preview/cp872722/2022/12/202212008462_500.jpg",
},
],
Comments: [
{
User: {
id: shortId.generate(),
nickname: faker.name.findName(),
},
content: faker.lorem.sentence(),
},
],
}));
export const LOAD_POSTS_REQUEST = "LOAD_POSTS_REQUEST";
export const LOAD_POSTS_SUCCESS = "LOAD_POSTS_SUCCESS";
export const LOAD_POSTS_FAILURE = "LOAD_POSTS_FAILURE";
export const ADD_POST_REQUEST = "ADD_POST_REQUEST";
export const ADD_POST_SUCCESS = "ADD_POST_SUCCESS";
export const ADD_POST_FAILURE = "ADD_POST_FAILURE";
export const REMOVE_POST_REQUEST = "REMOVE_POST_REQUEST";
export const REMOVE_POST_SUCCESS = "REMOVE_POST_SUCCESS";
export const REMOVE_POST_FAILURE = "REMOVE_POST_FAILURE";
export const ADD_COMMENT_REQUEST = "ADD_COMMENT_REQUEST";
export const ADD_COMMENT_SUCCESS = "ADD_COMMENT_SUCCESS";
export const ADD_COMMENT_FAILURE = "ADD_COMMENT_FAILURE";
export const addPost = (data) => ({
type: ADD_POST_REQUEST,
data,
});
export const addComment = (data) => ({
type: ADD_COMMENT_REQUEST,
data,
});
//리듀서란 이전 상태를 액션을 통해 다음 상태로 만들어내는 함수(단, 불변성은 지키면서)
//draft는 불변성 상관없이 바꾸면 immer가 알아서 불변성있게 만들어준다.
const reducer = (state = initialValue, action) =>
produce(state, (draft) => {
switch (action.type) {
//게시글 추가
case ADD_POST_REQUEST:
draft.addPostLoading = true;
draft.addPostDone = false;
draft.addPostError = null;
break;
case ADD_POST_SUCCESS:
draft.addPostLoading = false;
draft.addPostDone = true;
draft.mainPosts.unshift(action.data);
draft.imagePaths = [];
//unshift란 배열의 맨 앞에다가 추가하는 함수
break;
case ADD_POST_FAILURE:
draft.addPostLoading = false;
draft.addPostError = action.error;
break;
//게시글 불러오기
case LOAD_POSTS_REQUEST:
draft.loadPostsLoading = true;
draft.loadPostsDone = false;
draft.loadPostsError = null;
break;
case LOAD_POSTS_SUCCESS:
draft.loadPostsLoading = false;
draft.loadPostsDone = true;
draft.mainPosts = action.data.concat(draft.mainPosts);
//concat은 두개 이상의 배열을 합칠 때 사용
//action.data에는 더미데이터들이 들어있고 draft.mainPosts는 원래 데이터
draft.hasMorePost = draft.mainPosts.length < 50;
//50개보다 적으면 불러와야함
break;
case LOAD_POSTS_FAILURE:
draft.loadPostsLoading = false;
draft.loadPostsError = action.error;
break;
//댓글 추가
case ADD_COMMENT_REQUEST:
draft.addCommentLoading = true;
draft.addCommentDone = false;
draft.addCommentError = null;
break;
case ADD_COMMENT_SUCCESS:
//immer버전 (너무 간단함)
const post = draft.mainPosts.find(
(v) => v.id === action.data.postId
); //해당 게시글 찾기
post.Comments.unshift(dummyComment(action.data.content));
draft.addCommentLoading = false;
draft.addCommentDone = true;
//댓글 넣어주기
break;
//immer를 안 쓴 부분
// const postIndex = state.mainPosts.findIndex(
// (v) => v.id === action.data.postId
// );
// const post = { ...state.mainPosts[postIndex] };
// post.Comments = [
// dummyComment(action.data.content),
// ...post.Comments,
// ]; //얕은 복사
// const mainPosts = [...state.mainPosts];
// mainPosts[postIndex] = post; //댓글 추가하는 부분 너무어려움..
// //불변성을 지키다 보니 가독성이 너무 안좋음
// return {
// ...state,
// mainPosts,
// addCommentLoading: false,
// addCommentDone: true,
// };
case ADD_COMMENT_FAILURE:
draft.addCommentLoading = false;
draft.addCommentError = action.error;
break;
//게시글 삭제
case REMOVE_POST_REQUEST:
draft.removePostDone = false;
draft.removePostLoading = true;
draft.removePostError = null;
break;
case REMOVE_POST_SUCCESS:
draft.removePostLoading = false;
draft.removePostDone = true;
draft.mainPosts = draft.mainPosts.filter(
(v) => v.id !== action.data
);
break;
case REMOVE_POST_FAILURE:
draft.removePostLoading = false;
draft.removePostError = action.error;
break;
default:
break;
}
});
export default reducer;
여기서 Images안에 아무것도 들어있지 않아서 나타나는 오류같은데 잘 모르겠습니다.
답변을 작성해보세요.
0
윤채현
질문자2023.10.30
cover={post.Images?.[0] && <PostImages images={post.Images} />}
이렇게 수정하였는데 이번엔.. id쪽에서 오류가 발생하네요...
윤채현
질문자2023.10.30
import React, { useState } from "react";
import { Button, Card, Popover, Avatar, Image, List, Comment } from "antd";
import {
RetweetOutlined,
HeartOutlined,
MessageOutlined,
EllipsisOutlined,
HeartTwoTone,
} from "@ant-design/icons";
import { useCallback } from "react";
import { useSelector, useDispatch } from "react-redux";
import PropTypes from "prop-types";
import PostImages from "./PostImages";
import CommentForm from "./CommentForm";
import PostCardContent from "./PostCardContent";
import { REMOVE_POST_REQUEST } from "../reducers/post";
import FollowButton from "./FollowButton";
const PostCard = ({ post }) => {
//pages/index.js에서 mainPosts에서 하나씩 뜯어서 보내줌
const dispatch = useDispatch();
const [liked, setLiked] = useState(false); //좋아요
const [commentFormOpened, setCommentFormOpened] = useState(false);
//댓글창 열지 말지
const onToggleLike = useCallback(() => {
setLiked((prev) => !prev);
}, []); //좋아요를 한번 더 누르면 좋아요 취소
const onToggleComment = useCallback(() => {
setCommentFormOpened((prev) => !prev);
}, []); //폼 버튼 한번 더 누르면 폼 닫기
const onRemovePost = useCallback(() => {
dispatch({
type: REMOVE_POST_REQUEST,
data: post.id, //지울 포스트의 id
});
}, []);
const id = useSelector((state) => state.user.me?.id);
const { removePostloading } = useSelector((state) => state.post);
return (
<div style={{ marginBottom: 20 }}>
<Card
cover={post.Images?.[0] && <PostImages images={post.Images} />}
//이미지가 존재한다면 PostImages를 출력
actions={[
//카드 아래에 존재하는 것들
<RetweetOutlined key="retweet" />,
liked ? (
<HeartTwoTone
twoToneColor="red"
onClick={onToggleLike}
/>
) : (
<HeartOutlined key="heart" onClick={onToggleLike} />
),
<MessageOutlined onClick={onToggleComment} key="comment" />,
<Popover //더보기 같은 역할
key="more"
content={
<Button.Group>
{id && post.User.id === id ? (
<>
{/* 내가 쓴 글이면 수정, 삭제 */}
<Button>수정</Button>
<Button
type="danger"
onClick={onRemovePost}
loading={removePostloading}
>
삭제
</Button>
</>
) : (
// 내가 쓴 글이 아니라면
<Button>신고</Button>
)}
</Button.Group>
}
>
<EllipsisOutlined />
</Popover>,
]}
extra={id && <FollowButton post={post} />}
>
<Card.Meta //프로필과 내용 등
avatar={<Avatar>{post.User.nickname[0]}</Avatar>}
title={post.User.nickname}
description={<PostCardContent postData={post.content} />}
/>
</Card>
{commentFormOpened && (
//commentFormOpened가 true이면 열어라
<div>
{/* 어떤 게시글에 댓글을 남기는지.. */}
<CommentForm post={post} />
<List
header={`${post.Comments.length}개의 댓글`}
itemLayout="horizontal"
dataSource={post.Comments} //데이터는 여기서 가져와서
renderItem={(
item //이런식으로 출력한다
) => (
<li>
<Comment
author={item.User.nickname} //댓글쓴사람
avatar={
<Avatar>{item.User.nickname[0]}</Avatar> //아바타
}
content={item.content}
/>
</li>
)}
/>
</div>
)}
</div>
);
};
PostCard.PropTypes = {
post: PropTypes.shape({
id: PropTypes.number,
User: PropTypes.object,
content: PropTypes.string,
createdAt: PropTypes.object,
Comment: PropTypes.arrayOf(PropTypes.object),
Images: PropTypes.arrayOf(PropTypes.object),
}).isRequired,
};
export default PostCard;
이런식으로 postcard를 작성했습니다.
답변 1