작성
·
437
·
수정됨
0
에러메세지:ADD_POST_SUCCESS 까지 잘 되었고 content 에 id 도 잘 들어가 있는걸로 보입니다.
pages/index.js
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import AppLayout from "../components/AppLayout";
import PostCard from "../components/PostCard";
import PostForm from "../components/postForm";
import { LOAD_POSTS_REQUEST } from "../reducers/post";
import { LOAD_USER_REQUEST } from "../reducers/user";
const Home = () => {
const me = useSelector((state) => state.user.me);
const { mainPosts, hasMorePosts, isLoadingPosts } = useSelector(
(state) => state.post
);
const dispatch = useDispatch();
useEffect(() => {
dispatch({
type: LOAD_USER_REQUEST,
});
dispatch({
type: LOAD_POSTS_REQUEST,
});
}, []);
useEffect(() => {
function onScroll() {
if (
window.scrollY + document.documentElement.clientHeight >
document.documentElement.scrollHeight - 300
) {
if (hasMorePosts && !isLoadingPosts) {
dispatch({
type: LOAD_POSTS_REQUEST,
});
}
}
}
window.addEventListener("scroll", onScroll);
return () => {
window.removeEventListener("scroll", onScroll);
};
}, []);
return (
<AppLayout>
{me && <PostForm />}
{mainPosts.map((post) => (
<PostCard key={post.id} post={post} />
))}
</AppLayout>
);
};
export default Home;
reducers/post.js
import produce from "immer";
export const initialState = {
mainPosts: [],
imagePaths: [],
hasMorePosts: true,
isAddingPost: false,
isAddedPost: false,
isAddPostErr: null,
isRemovingPost: false,
isRemovedPost: false,
isRemovePostErr: null,
isAddingComment: false,
isAddedComment: false,
isAddCommentErr: null,
isRemovingComment: false,
isRemovedComment: false,
isRemoveCommentErr: null,
isLoadingPosts: false,
isLoadedPosts: false,
isLoadPostsErr: null,
};
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,
});
const reducer = (state = initialState, action) => {
return produce(state, (draft) => {
switch (action.type) {
case ADD_POST_REQUEST:
draft.isAddingPost = true;
draft.isAddedPost = false;
draft.isAddPostErr = null;
break;
case ADD_POST_SUCCESS:
draft.isAddingPost = false;
draft.mainPosts.unshift(action.data);
draft.isAddedPost = true;
break;
case ADD_POST_FAILURE:
draft.isAddingPost = false;
draft.isAddedPost = false;
draft.isAddPostErr = action.error;
break;
case REMOVE_POST_REQUEST:
draft.isRemovingPost = true;
draft.isRemovedPost = false;
draft.isRemovePostErr = null;
break;
case REMOVE_POST_SUCCESS:
draft.isRemovingPost = false;
draft.mainPosts = state.mainPosts.filter((v) => v.id !== action.data);
draft.isRemovedPost = true;
draft.isRemovePostErr = null;
break;
case REMOVE_POST_FAILURE:
draft.isRemovingPost = false;
draft.isRemovedPost = false;
draft.isRemovePostErr = action.error;
break;
case ADD_COMMENT_REQUEST:
draft.isAddingComment = true;
draft.isAddedComment = false;
draft.isAddCommentErr = null;
break;
case ADD_COMMENT_SUCCESS:
draft.isAddingComment = false;
const post = draft.mainPosts.find((v) => v.id === action.data.PostId);
post.Comments.unshift(action.data);
draft.isAddedComment = true;
break;
case ADD_COMMENT_FAILURE:
draft.isAddingComment = false;
draft.isAddedComment = false;
draft.isAddCommentErr = action.error;
break;
case LOAD_POSTS_REQUEST:
draft.isLoadingPosts = true;
draft.isLoadedPosts = false;
draft.isLoadPostsErr = null;
break;
case LOAD_POSTS_SUCCESS:
draft.isLoadingPosts = false;
draft.mainPosts = draft.mainPosts.concat(action.data);
draft.isLoadedPosts = true;
break;
case LOAD_POSTS_FAILURE:
draft.isLoadingPosts = false;
draft.isLoadedPosts = false;
draft.isLoadPostsErr = action.error;
break;
default:
break;
}
});
};
export default reducer;
sagas/post.js
import { delay, all, fork, put, takeLatest, call } from "redux-saga/effects";
import axios from "axios";
import {
ADD_POST_REQUEST,
ADD_POST_SUCCESS,
ADD_POST_FAILURE,
ADD_COMMENT_FAILURE,
ADD_COMMENT_SUCCESS,
ADD_COMMENT_REQUEST,
REMOVE_POST_REQUEST,
REMOVE_POST_SUCCESS,
REMOVE_POST_FAILURE,
LOAD_POSTS_REQUEST,
LOAD_POSTS_SUCCESS,
LOAD_POSTS_FAILURE,
} from "../reducers/post";
import { ADD_POST_TO_ME, REMOVE_POST_FROM_ME } from "../reducers/user";
function addPostAPI(data) {
return axios.post(
"/post",
{ content: data },
{
withCredentials: true,
}
);
}
function* addPost(action) {
try {
const result = yield call(addPostAPI, action.data);
yield put({ type: ADD_POST_SUCCESS, content: result.data });
yield put({
type: ADD_POST_TO_ME,
data: result.data.id,
});
} catch (err) {
console.log(err);
yield put({
type: ADD_POST_FAILURE,
error: err.response.data,
});
}
}
function removePostAPI(data) {
return axios.delete("/post", data);
}
function* removePost(action) {
try {
yield delay(1000);
yield put({
type: REMOVE_POST_SUCCESS,
data: action.data,
});
yield put({
type: REMOVE_POST_FROM_ME,
data: action.data,
});
} catch (err) {
yield put({
type: REMOVE_POST_FAILURE,
error: err.response.data,
});
}
}
function addCommentAPI(data) {
return axios.post(`/post/${data.postId}/comment`, data); //POST /post/1/comment
}
function* addComment(action) {
try {
const result = yield call(addCommentAPI, action.data);
yield put({ type: ADD_COMMENT_SUCCESS, data: result.data });
} catch (err) {
console.log(err);
yield put({
type: ADD_COMMENT_FAILURE,
error: err,
});
}
}
function loadPostsAPI() {
return axios.get(`/posts`);
}
function* loadPosts(action) {
try {
const result = yield call(loadPostsAPI, action.data);
yield put({ type: LOAD_POSTS_SUCCESS, data: result.data });
} catch (err) {
console.log(err);
yield put({
type: LOAD_POSTS_FAILURE,
error: err.response.data,
});
}
}
function* watchAddPost() {
yield takeLatest(ADD_POST_REQUEST, addPost);
}
function* watchRemovePost() {
yield takeLatest(REMOVE_POST_REQUEST, removePost);
}
function* watchAddComment() {
yield takeLatest(ADD_COMMENT_REQUEST, addComment);
}
function* watchLoadPosts() {
yield takeLatest(LOAD_POSTS_REQUEST, loadPosts);
}
export default function* postSaga() {
yield all([
fork(watchAddPost),
fork(watchRemovePost),
fork(watchAddComment),
fork(watchLoadPosts),
]);
}
routes/posts.js
const express = require("express");
const { Post, Image, User, Comment } = require("../models");
const router = express.Router();
router.get("/", async (req, res, next) => {
// GET /posts
try {
const posts = await Post.findAll({
limit: 10,
order: [
["createdAt", "DESC"],
[Comment, "createdAt", "DESC"],
],
include: [
{
model: User,
attributes: ["id", "nickname"],
},
{
model: Image,
},
{
model: Comment,
include: [{ model: User, attributes: ["id", "nickname"] }],
},
],
});
res.status(200).json(posts);
} catch (err) {
console.error(err);
next(err);
}
});
module.exports = router;
sql 테이블도 잘 들어가있고, 새로 고침 하면 포스팅은 잘 되어 있습니다.