-
카테고리
-
세부 분야
풀스택
-
해결 여부
미해결
무한정 back으로부터 post 데이터를 불러와요!
21.12.26 20:38 작성 조회수 108
0
안녕하세요 zerocho 선생님...
다른게 아니라 이 부분에서 아주 크나큰 문제에 맞닥뜨려
작업을 못하고 있습니다.
pages/index.js에서 useEffect를 사용해서
첫 페이지에 오면 로그인 유무를 판단하고
또 기존에 있던 게시글을 불러와야 하는것을 잘 아는데
문제는 로그인할 경우에는 딱 한번만 LOAD_MY_INFO_REQUEST를 잘 수행하는데 LOAD_POST_REQUEST를하는순간 무한 응답을 합니다.
post man에서 받아온 데이터를 다음과 같습니다.
사실 저는 springboot를 back으로 사용하고 있는데
이유는 JPA를 좀 사용해보고 싶어서 였습니다.
next.js를 아예 안쓰는것이 나앗던 것 같지만 처음에 강의를 접하고 할때는 아무것도 몰라서... 무진 후회중.. 그냥따라할걸...
하여간... 기존의 데이터도 이런 식으로 받아오는데 문제는
무한 응답을 요청하니까 도대체 어디서 잘못된건지 모르겠다는 것입니다. ㅠㅠ 제발좀 도와주십시오.;..
pages/index.js
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import AppLayout from "../components/AppLayout";
import PostCard from "../components/middleComponent/Post/PostCard";
import PostForm from "../components/middleComponent/Post/PostForm";
import { LOAD_POST_REQUEST } from "../reducers/post";
import { LOAD_MY_INFO_REQUEST } from "../reducers/user";
const Home = () => {
const dispatch = useDispatch();
const { me } = useSelector((state) => state.user);
const { mainPosts, hasMorePost, loadPostLoading } = useSelector((state) => state.post);
useEffect(() => {
console.log("useEffect in index.js")
dispatch({
type: LOAD_MY_INFO_REQUEST
});
// dispatch({
// type: LOAD_POST_REQUEST,
// });
}, [hasMorePost, loadPostLoading]);
useEffect(() => {
function onScroll() {
if (window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300){
if (hasMorePost && !loadPostLoading) {
dispatch({
type: LOAD_POST_REQUEST,
});
}
}
}
window.addEventListener('scroll', onScroll);
return () => {
window.removeEventListener('scroll', onScroll);
}
}, []);
console.log(mainPosts);
return (
<AppLayout>
{me && <PostForm />}
{mainPosts.map((post) => <PostCard key={post.id} post={post}/>)}
</AppLayout>
);
}
export default Home;
reducers/post.js
import shortId from 'shortid';
import produces, { produce } from 'immer';
import faker from 'faker';
import { ConsoleSqlOutlined } from '@ant-design/icons';
export const initialState = {
mainPosts: [],
imagePaths: [],
hasMorePost: true,
loadPostLoading: false,
loadPostDone: false,
loadPostError: null,
addPostLoading: false,
addPostDone: false,
addPostError: null,
addCommentLoading: false,
addCommentDone: false,
addCommentError: null,
removePostLoading: false,
removePostDone: false,
removePostError: 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: faker.image.imageUrl(),
}],
Comments: [{
User: {
id: shortId.generate(),
nickname: faker.name.findName()
},
content: faker.lorem.sentence(),
}],
}));
export const LOAD_POST_REQUEST = 'LOAD_POST_REQUEST';
export const LOAD_POST_SUCCESS = 'LOAD_POST_SUCCESS';
export const LOAD_POST_FAILURE = 'LOAD_POST_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 ADD_COMMENT_REQUEST = 'ADD_COMMENT_REQUEST';
export const ADD_COMMENT_SUCCESS = 'ADD_COMMENT_SUCCESS';
export const ADD_COMMENT_FAILURE = 'ADD_COMMENT_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_POST_TO_ME = 'ADD_POST_TO_ME';
export const REMOVE_POST_OF_ME = 'REMOVE_POST_OF_ME';
export const addPost = (data) => ({
type: ADD_POST_REQUEST,
data
})
export const addComment = (data) => ({
type: ADD_COMMENT_REQUEST,
data
})
// const dummyPost = (data) => ({
// id: data.id,
// content: data.content,
// User: {
// id: 1,
// nickname: 'thelovedaejeon',
// },
// Images: [],
// Comments: [],
// });
// const dummyComment = (data) => ({
// id: shortId.generate(),
// content: data,
// User: {
// id: 1,
// nickname: 'thelovedaejeon',
// },
// })
//이전 상태를 action을 통해 다음 상태로 만들어 내는 함수 (불변성을 지키면서)
const reducer = (state = initialState, action) => {
return produce (state, (draft) => {
switch (action.type){
case LOAD_POST_REQUEST:
draft.loadPostLoading = true;
draft.loadPostDone= false;
draft.loadPostError= null;
break;
case LOAD_POST_SUCCESS:
draft.loadPostLoading = false;
draft.loadPostDone= true;
draft.mainPosts = action.data.concat(draft.mainPosts);
draft.hasMorePost = false;
break;
case LOAD_POST_FAILURE:
draft.loadPostLoading = false;
draft.loadPostError = action.error;
break;
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(dummyPost(action.data));
break;
case ADD_POST_FAILURE:
draft.addPostLoading = false;
draft.addPostError = action.error;
break;
case REMOVE_POST_REQUEST:
draft.removePostLoading = true;
draft.removePostDone = false;
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;
case ADD_COMMENT_REQUEST:
draft.addCommentLoading = true;
draft.addCommentDone = false;
draft.addCommentError = null;
break;
case ADD_COMMENT_SUCCESS:{
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;
// 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;
default:
break;
}
});
};
export default reducer;
sagas/post.js
import { delay, fork, all, takeLatest, put, call} from "redux-saga/effects";
import shortId from "shortid";
import axios from 'axios';
// import Axios from 'axios';
// import qs from 'query-string';
import Cookies from 'universal-cookie';
import {
ADD_COMMENT_FAILURE,
ADD_COMMENT_REQUEST,
ADD_COMMENT_SUCCESS,
ADD_POST_FAILURE,
ADD_POST_REQUEST,
ADD_POST_SUCCESS,
ADD_POST_TO_ME,
generateDummyPost,
LOAD_POST_FAILURE,
LOAD_POST_REQUEST,
LOAD_POST_SUCCESS,
REMOVE_POST_FAILURE,
REMOVE_POST_REQUEST,
REMOVE_POST_SUCCESS
} from "../reducers/post";
import { REMOVE_POST_OF_ME } from "../reducers/user";
const cookies = new Cookies();
function addPostAPI(data) {
const accessToken = cookies.get("accessToken");
const userEmail = cookies.get("userEmail");
const newObj = {
description : data,
email : userEmail
}
return axios.post('/auth/post', newObj,{
headers:{
'Authorization': `Bearer ${accessToken}`,
"Content-Type": "application/json"
}
});
}
function* addPost(action) {
try {
const result = yield call(addPostAPI, action.data);
yield put({
type: ADD_POST_SUCCESS,
data: {
id : result.data.postId,
content: action.data
}
})
yield put({
type: ADD_POST_TO_ME,
data: result.data.postId,
})
} catch (error) {
console.log(error);
yield put({
type: ADD_POST_FAILURE,
data: error.data
})
}
}
function loadPostAPI(data) {
return axios.get('/api/posts');
}
function* loadPost(action) {
try {
const result = yield call(loadPostAPI);
console.log(result);
console.log(result.data);
yield put({
type: LOAD_POST_SUCCESS,
data: result.data.result,
});
} catch (error) {
console.log(error);
yield put({
type: LOAD_POST_FAILURE,
data: error.data
})
}
}
function removePostAPI(data) {
return axios.post('/api/post', data);
}
function* removePost(action) {
try {
delay(1000);
// const result = yield call(addPostAPI, action.data);
const id = shortId.generate();
yield put({
type: REMOVE_POST_SUCCESS,
data: action.data
});
yield put({
type: REMOVE_POST_OF_ME,
data: action.data
})
} catch (error) {
yield put({
type: REMOVE_POST_FAILURE,
data: error.data
})
}
}
function addCommentAPI(data) {
return axios.post('/api/post/${data.postId}/comment', data);
}
function* addComment(action) {
try {
delay(1000);
// const result = yield call(addPostAPI, action.data);
yield put({
type: ADD_COMMENT_SUCCESS,
data: action.data
})
} catch (error) {
yield put({
type: ADD_COMMENT_FAILURE,
data: error.data
})
}
}
function* watchAddPost(){
yield takeLatest(ADD_POST_REQUEST, addPost); // 첫번째것만 하고 싶으면 takeLeading
}
function* watchLoadPost(){
yield takeLatest(LOAD_POST_REQUEST, loadPost); // 첫번째것만 하고 싶으면 takeLeading
}
function* watchRemovePost(){
yield takeLatest(REMOVE_POST_REQUEST, removePost); // 첫번째것만 하고 싶으면 takeLeading
}
function* watchAddComment(){
yield takeLatest(ADD_COMMENT_REQUEST, addComment); // 첫번째것만 하고 싶으면 takeLeading
}
export default function* postSaga(){
yield all([
fork(watchLoadPost),
fork(watchAddPost),
fork(watchRemovePost),
fork(watchAddComment),
])
};
답변을 작성해보세요.
1
답변 1