작성
·
224
·
수정됨
0
안녕하세요 선생님
카카오톡 공유하기 까지 듣고 화면을 테스트해보고 있는데
Minified React error 이 에러가 떠서 질문드립니다.
메인화면, 상세보기에서 게시글이 있을때 나옵니다.
Uncaught Error: Minified React error #418; visit https://reactjs.org/docs/error-decoder.html?invariant=418 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
at lg (framework-ecc4130bc7a58a64.js:9:46457)
at i (framework-ecc4130bc7a58a64.js:9:121052)
at oO (framework-ecc4130bc7a58a64.js:9:99019)
at framework-ecc4130bc7a58a64.js:9:98886
at oF (framework-ecc4130bc7a58a64.js:9:98893)
at oS (framework-ecc4130bc7a58a64.js:9:93932)
at x (framework-ecc4130bc7a58a64.js:33:1364)
at MessagePort.T (framework-ecc4130bc7a58a64.js:33:1894)
검색해봤더니 hydrate 쪽 이슈더라구요.
혼자서 풀어보다가 잘 풀리지 않아서 여쭤봅니다.
혹시 제로초님은 저런 에러가 나지 않으시는지
난다면 어느 로직을 확인해야할지 조언 부탁드립니다.
/pages/post/[id].js
import axios from 'axios';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { useSelector } from 'react-redux';
import AppLayout from '../../components/AppLayout';
import PostCard from '../../components/PostCard';
import { loadPost } from '../../reducers/post';
import { loadMyInfo } from '../../reducers/user';
import wrapper from '../../store/configurStore';
const Post = () => {
const router = useRouter();
const { id } = router.query;
const { singlePost } = useSelector((state) => state.post);
return (
<AppLayout>
{singlePost ? (
<>
<Head>
<title>
{singlePost?.User.nickname}
님의 글
</title>
<meta name="description" content={singlePost.content} />
<meta
property="og:title"
content={`${singlePost.User.nickname}님의 게시글`}
/>
<meta property="og:description" content={singlePost.content} />
<meta
property="og:image"
content={
singlePost.Images[0]
? singlePost.Images[0].src
: 'https://nodebird.com/favicon.ico'
}
/>
<meta
property="og:url"
content={`https://nodebird.com/post/${id}`}
/>
</Head>
<PostCard post={singlePost}>{id}번 게시글</PostCard>
</>
) : (
<div>존재하지 않는 게시물입니다.</div>
)}
</AppLayout>
);
};
export const getServerSideProps = wrapper.getServerSideProps(
(store) =>
async ({ req, params }) => {
const cookie = req ? req.headers.cookie : '';
axios.defaults.headers.Cookie = '';
// 쿠키가 브라우저에 있는경우만 넣어서 실행
// (주의, 아래 조건이 없다면 다른 사람으로 로그인 될 수도 있음)
if (req && cookie) {
axios.defaults.headers.Cookie = cookie;
}
await store.dispatch(loadMyInfo());
await store.dispatch(loadPost(params.id));
},
);
export default Post;
/components/PostCard.js
import {
RetweetOutlined,
HeartOutlined,
HeartTwoTone,
MessageOutlined,
EllipsisOutlined,
} from '@ant-design/icons';
import { Card, Popover, Button, Avatar, List } from 'antd';
import dayjs from 'dayjs';
import Link from 'next/link';
import PropTypes from 'prop-types';
import { useState, useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import CommentForm from './CommentForm';
import Followbutton from './FollowButton';
import PostCardContent from './PostCardContent';
import PostImages from './PostImages';
import {
removePostRequestAction,
likePostRequestAction,
unLikePostRequestAction,
retweetRequestAction,
} from '../reducers/post';
dayjs.locale('ko');
const PostCard = ({ post }) => {
// const { me: {id} } = useSelector((state) => state.user);
// const id = me && me.id;
// const id = me?.id; // 옵셔널 체이닝 연산자
const { removePostLoading } = useSelector((state) => state.post);
const dispatch = useDispatch();
const [commentFormOpend, setCommentFormOpend] = useState(false);
const id = useSelector((state) => state.user.me?.id);
const liked = post.Likers.find((d) => d.id === id);
const onLike = useCallback(() => {
if (!id) {
alert('로그인이 필요합니다.');
}
dispatch(likePostRequestAction(post.id));
}, [id]);
const onUnLike = useCallback(() => {
if (!id) {
alert('로그인이 필요합니다.');
}
dispatch(unLikePostRequestAction(post.id));
}, [id]);
const onToggleComment = useCallback(() => {
setCommentFormOpend((prev) => !prev);
}, []);
const onRemovePost = useCallback(() => {
if (!id) {
alert('로그인이 필요합니다.');
}
dispatch(removePostRequestAction({ id: post.id }));
}, [id]);
const onRetweet = useCallback(() => {
if (!id) {
alert('로그인이 필요합니다.');
}
dispatch(retweetRequestAction(post.id));
}, [id]);
return (
<div style={{ marginTop: 10 }}>
<Card
cover={post.Images[0] && <PostImages images={post.Images} />}
actions={[
// 배열안에 들어가는 것들은 다 key를 넣어줘야 한다.
<RetweetOutlined key="retweet" onClick={onRetweet} />,
liked ? (
<HeartTwoTone
key="heart"
twoToneColor="#eb2f96"
onClick={onUnLike}
/>
) : (
<HeartOutlined key="heart" onClick={onLike} />
),
<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} />}
title={
post.RetweetId ? `${post.User.nickname}님이 리트윗하셨습니다.` : null
}
>
{post.RetweetId && post.Retweet ? (
<Card
cover={
post.Retweet.Images[0] && (
<PostImages images={post.Retweet.Images} />
)
}
>
<div style={{ float: 'right' }}>
{dayjs(post.createdAt).format('YYYY.MM.DD')}
</div>
<Card.Meta
avatar={
<Link href={`/user/${post.Retweet.User.id}`}>
<Avatar>{post.Retweet.User?.nickname[0]}</Avatar>
</Link>
}
title={post.Retweet.User?.nickname}
description={<PostCardContent postData={post.Retweet.content} />}
/>
</Card>
) : (
<>
<div style={{ float: 'right' }}>
{dayjs(post.createdAt).format('YYYY.MM.DD')}
</div>
<Card.Meta
avatar={
<Link href={`/user/${post.User.id}`}>
<Avatar>{post.User?.nickname[0]}</Avatar>
</Link>
}
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={
<Link href={`/user/${item.User.id}`}>
<Avatar>{item.User.nickname[0]}</Avatar>
</Link>
}
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),
Likers: PropTypes.arrayOf(PropTypes.object),
RetweetId: PropTypes.number,
Retweet: PropTypes.objectOf(PropTypes.any),
}).isRequired,
};
export default PostCard;
여유되실때 한번 봐주시면 감사하겠습니다
네 이번에 처음 나온 에러라서 찾아보다 여쭤봤었습니다.
흠.. 수업 다 듣고나서 찾아봐야겠습니다.
답변 감사합니다!