현재 간단한 게시글 커뮤니티 기능을 만들고 있습니다.
프론트엔드는 JavaScript, React.js, 백엔드는 Python, Django REST로 구현중입니다.
장고 백엔드의 데이터를 프론트엔드에서 fetch로 받아오는 상황에서
아래와 같은 에러를 마주하였습니다.
에러를 읽어보면, Objects are not valid as a React Child라고 합니다.
제 코드의 어딘가에서, 객체가 문제를 일으키고 있는 것으로 보입니다.
해당 에러는 주로 JSX안에 객체를 통째로 렌더링 하려 할 때 발생합니다.
제 코드 중, 문제가 되었던 파일은 다음과 같습니다.
프로젝트의 전체적인 구조를 우선 간략히 살펴보고,
무엇이 에러를 발생시킨 것인지 후에 알아보겠습니다.
//프론트엔드 로직
import React, { useState, useEffect } from "react";
const Post = () => {
const [post, setPost] = useState([]);
useEffect(() => {
const postDataOriginUrl = "http://127.0.0.1:8000/api/";
fetch(postDataOriginUrl)
.then((resopnse) => resopnse.json())
.then((data) => setPost(data));
}, []);
console.log(post);
return (
<div>
{post.map((posting) => (
<div>
<li key={posting.id}>{posting}</li>
</div>
))}
</div>
);
};
export default Post;
이렇게, 프론트엔드 단에서 장고 백엔드의 주소인 http://127.0.0.1:8000/api/
에서 데이터를 받아오고 있습니다.
파이썬으로 작성한 백엔드 코드를 보면,
#코드 생략
#게시물 테이블
class Post(models.Model):
#코드 생략
#게시물 출간 옵션 - 임시저장, 공개발행
options = (
('draft', 'Draft'),
('published', 'Published')
)
category = models.ForeignKey(
Category, on_delete = models.PROTECT, default = 1)
title = models.TextField(max_length = 200)
content = models.TextField()
created_at = models.DateTimeField(default = timezone.now)
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="myblog_posts"
)
#게시물 공개로 할지 임시저장할진
status = models.CharField(max_length=10, choices=options, default='published')
#코드 생략
당연한 얘기지만 각 게시글 데이터는 객체 형태로 저장됩니다.
장고 개발 서버에서 API View를 이용해 실제 데이터의 형태를 살펴보면,
이렇게, 객체를 요소로 하는 배열 데이터를 프론트엔드 단으로 전송하고 있음을 알 수 있습니다.
즉, 프론트엔드의 코드 중
//코드 생략
const [post, setPost] = useState([]);
useEffect(() => {
const postDataOriginUrl = "http://127.0.0.1:8000/api/";
fetch(postDataOriginUrl)
.then((resopnse) => resopnse.json())
.then((data) => setPost(data));
}, []);
이 부분에서, post State엔 객체를 요소로 하는 배열이 담기는 것입니다.
이후 아래와 같이 객체 자체를 JSX구문에서 렌더링하면, 에러가 발생합니다.
return (
<div>
{post.map((posting) => (
<div>
<li key={posting.id}>{posting}</li>
</div>
))}
</div>
);
};
저는 객체 자체가 화면에 출력될 것을 기대했지만,
JSX는 객체 자체를 직접 렌더링하는 것을 지원하지 않습니다.
대신, 객체의 속성 각각에 접근하여 따로 렌더링 해주어야 합니다.
객체의 속성 각각에 접근하여 문제를 해결할 수 있습니다.
아래는 수정된 코드입니다.
return (
<div>
{post.map((posting) => (
<div key={posting.id}>
<li>{posting.title}</li>
<li>{posting.content}</li>
<li>{posting.author}</li>
</div>
))}
</div>
);
앞으로 객체 데이터를 화면에 렌더링 할 때는,
객체를 직접 렌더링 하는 것이 아니라,
객체의 속성 각각에 따로 접근해 하나씩 렌더링해주어야 합니다.
감사합니다.