인프런 커뮤니티 질문&답변

챠챠_님의 프로필 이미지

작성한 질문수

[리뉴얼] React로 NodeBird SNS 만들기

게시글 불러오기

센셕4 게시물 불러오기 postcard.js에서 post.User.nickname[0]에러

작성

·

226

·

수정됨

0

안녕하세요

센셕4 게시물 불러오기 postcard.js에서 post.User.nickname[0]에러가 발생해서 처음엔 간단하게

/components/postcard.js

<Card.Meta avatar={<Avatar>{post.User?.nickname[0]}</Avatar>} title={post.User?.nickname} description={<PostCardContent postData={post.content} />} />

이런식으로 해결했었습니다.

아 같은 파일 위치에서

{id && post.User?.id === id ? (
									<>
										<Button type='primary' key='modify'>
											수정
										</Button>
										<Button type='danger' key={"delete"} onClick={onRemovePost} loading={removePostLoading}>
											삭제
										</Button>
									</>
								) : (
									<Button type='dashed' key={"report"}>
										신고
									</Button>
								)}
post.User?.id

이것도 같은 식으로 처리했었습니다.

그런데 제로초님 코딩을 몇번 다시봤더니

비슷한 에러가 코멘트에서 났었는데

/routes/posts.js

const express = require("express");

const router = express.Router();
const { Post, User, Image, Comment } = require("../models");

// GET /posts 여러 게시글 가져오기
router.get("/", async (req, res, next) => {
	try {
		const posts = await Post.findAll({
			limit: 10, 
			include: [
				{
					model: User,
					attributes: ["id", "nickname"],
				},
				{
					model: Image,
				},
				{
					model: Comment,
					include: [
						{
							model: User,
							attributes: ["id", "nickname"],
						},
					],
				},
			],
		});
		res.status(200).json(posts);
	} catch (error) {
		console.error(error);
		next(error);
	}
});

module.exports = router;

이런식으로 데이 필요한 id, nickname을 넣어주셔서 ?를 붙이지 않고 해결하셨더라구요.
혹시 저 nickname부분도 위와같이 백단에서 코드를 수정해서 고칠수 있을까요?

따라서 해봤는데 잘 안되서 여쭤봅니다.

답변 3

1

안녕하세요, 인프런 AI 인턴입니다.

챠챠_님께서 겪고 계신 post.User.nickname[0] 관련 문제는 post.User 객체가 정의되지 않아 발생하는 undefined 문제로 보입니다. 말씀하신 내용으로 미루어보아 post.User 객체의 존재를 확인 후 nickname에 접근하려면 옵셔널 체이닝(?.)을 활용하는 것이 일반적인 해결방안 중 하나입니다. 그러나 백엔드에서 데이터를 받아올 때 해당 데이터가 정확히 포함되도록 조치하는 것이 더 근본적인 해결책일 수 있습니다.

챠챠_님은 이미 옵셔널 체이닝으로 일시적으로 문제를 해결하고 계셨고, 유사한 문제에 대해 백엔드의 코드를 수정하여 해결하려는 의도를 보여주셨습니다. 이와 관련해서는 다음과 같은 접근 방법을 고려해볼 수 있습니다.

  1. 백엔드에서 Post.findAll()을 사용하여 데이터를 가져올 때, include 옵션을 통하여 User 모델에서 nicknameid 정보를 가져오도록 설정하고 있습니다. 이 설정이 적절하게 돼 있는지 확인해보셨음에도 문제가 해결되지 않는 상황입니다.

  2. 문제가 지속된다면, 쿼리를 실행하기 전 Post, User 등의 모델 간 연결 관계가 데이터베이스 내에서 올바르게 설정되어 있는지 확인해볼 필요가 있습니다. Sequelize 설정에서 연결 관계 설정이 정확히 반영되어 있는지, 연결된 모델의 속성이 정확한지 등을 점검해보세요.

  3. 또한 서버 로그 혹은 디버깅을 통해서 실제로 Post.findAll()로 가져온 데이터 내 User 객체가 포함되어 있는지, 그리고 nickname 정보가 정상적으로 있는지를 확인해볼 필요가 있습니다.

문제의 직접적 해결 방안을 제공하는 링크를 찾기 어렵지만, 비슷한 문제를 경험하신 다른 학습자의 사례를 참고하는 것이 도움이 될 수 있습니다. 예를 들어, 다음 질문과 답변에서는 User.nicknameundefined로 나타나는 문제를 다루었으며, 여러 해결 방안을 제시하고 있습니다.

  • null 에러 질문드립니다. - 이 경우, post.User 객체의 존재 여부를 확인하지 않아 발생하는 문제로, post.User?.nickname과 같이 Optional Chaining을 활용하여 해결했습니다.

챠챠_님의 경우처럼, 클라이언트 측에서 이미 Optional Chaining을 통해 일시적 해결을 보신 것처럼, 백엔드에서 데이터를 정확히 전달하도록 코드를 확인하는 것이 좋습니다. include 옵션에서 User 모델의 데이터를 포함시켜 주고 있는지, 그리고 데이터 모델 간의 관계 정의가 정확한지 확인해보시기 바랍니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

지금 백단 코드면 에러가 안 나야 정상입니다.

에러가 난다는 것은 게시글 등록할 때 유저 아이디가 제대로 저장 안 되고 있는 것 같습니다.

0

챠챠_님의 프로필 이미지
챠챠_
질문자

혹시나해서

postcard.js의 전체코드는

아래와 같습니다.

import { Card, Popover, Button, Avatar, List } from "antd";
import { RetweetOutlined, HeartOutlined, HeartTwoTone, MessageOutlined, EllipsisOutlined } from "@ant-design/icons";
import { useState, useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import PropTypes from "prop-types";
import { removePostRequestAction } from "../reducers/post";

import PostImages from "./PostImages";
import CommentForm from "./CommentForm";
import PostCardContent from "./PostCardContent";
import Followbutton from "./FollowButton";

const PostCard = ({ post }) => {
	// const { me: {id} } = useSelector((state) => state.user);
	// const id = me && me.id;
	// const id = me?.id; // 옵셔널 체이닝 연산자
	const id = useSelector((state) => state.user.me?.id);
	const { removePostLoading } = useSelector((state) => state.post);
	const dispatch = useDispatch();
	const [liked, setLiked] = useState(false);
	const [commentFormOpend, setCommentFormOpend] = useState(false);

	const onToggleLike = useCallback(() => {
		setLiked((prevLiked) => !prevLiked);
	}, []);
	const onToggleComment = useCallback(() => {
		setCommentFormOpend((prev) => !prev);
	}, []);
	const onRemovePost = useCallback(() => {
		dispatch(removePostRequestAction({ id: post.id }));
	}, []);
	return (
		<div style={{ marginTop: 10 }}>
			<Card
				cover={post.Images[0] && <PostImages images={post.Images} />}
				actions={[
					// 배열안에 들어가는 것들은 다 key를 넣어줘야 한다.
					<RetweetOutlined key='retweet' />,
					liked ? <HeartTwoTone key='heart' twoToneColor={"#eb2f96"} onClick={onToggleLike} /> : <HeartOutlined key='heart' onClick={onToggleLike} />,
					<MessageOutlined key={"comment"} onClick={onToggleComment} />,
					<Popover
						key={"more"}
						content={
							<Button.Group>
								{id && post.User?.id === id ? (
									<>
										<Button type='primary' key='modify'>
											수정
										</Button>
										<Button type='danger' key={"delete"} onClick={onRemovePost} loading={removePostLoading}>
											삭제
										</Button>
									</>
								) : (
									<Button type='dashed' key={"report"}>
										신고
									</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>
			{commentFormOpend && (
				<div>
					{/* 게시글의 아이디 위해서 post 넘겨줌 */}
					<CommentForm post={post} />
					<List
						header={`${post.Comments.length}개의 댓글`}
						itemLayout='horizontal'
						dataSource={post.Comments}
						renderItem={(item) => (
							<List.Item key={item.id}>
								<List.Item.Meta title={item.User?.nickname} avatar={<Avatar>{item.User?.nickname[0]}</Avatar>} description={item.content} />
							</List.Item>
						)}
					/>
				</div>
			)}
		</div>
	);
};

PostCard.propTypes = {
	post: PropTypes.shape({
		id: PropTypes.number,
		User: PropTypes.object,
		content: PropTypes.string,
		createdAt: PropTypes.string,
		Comments: PropTypes.arrayOf(PropTypes.object),
		Images: PropTypes.arrayOf(PropTypes.object),
	}).isRequired,
};

export default PostCard;
챠챠_님의 프로필 이미지

작성한 질문수

질문하기