-
카테고리
-
세부 분야
풀스택
-
해결 여부
미해결
load_posts_request가 success가 완료 뜨기 전에 또 실행됩니다 ㅠ
22.06.10 19:14 작성 조회수 108
0
강의에서 알려주신 대로 로딩되는 동안은 실행되지 않도록 loadingPostsLoading이 false일때 실행되도록 조건문을 걸어줬는데도 저는 계속 load_posts_request가 일어납니다. redux devtools를 살펴보면 loadingPostsLoading이 true일때도 request가 요청된 걸로 나오는데 조건문이 실행이 안되는 이유가 어디서 잘못된건지 모르겠습니다.
## pages/index.js
import React, { useEffect } from "react";
import { useSelector, useDispatch } 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";
const Home = () => {
const dispatch = useDispatch();
const { me } = useSelector((state) => state.user);
const { mainPosts, hasMorePost, loadPostsLoading } = useSelector(
(state) => state.post
);
useEffect(() => {
dispatch({
type: LOAD_POSTS_REQUEST,
});
}, []);
useEffect(() => {
function onScroll() {
console.log(
window.scrollY,
document.documentElement.clientHeight,
document.documentElement.scrollHeight
);
if (
window.scrollY + document.documentElement.clientHeight >
document.documentElement.scrollHeight - 300
) {
if (hasMorePost && !loadPostsLoading) {
dispatch({
type: LOAD_POSTS_REQUEST,
});
}
}
}
window.addEventListener("scroll", onScroll);
return () => {
window.removeEventListener("scroll", onScroll);
};
}, [hasMorePost, loadPostsLoading]);
return (
<AppLayout>
{me && <PostForm />}
{mainPosts.map((post) => (
<PostCard key={post.id} post={post} />
))}
</AppLayout>
);
};
export default Home;
##reducer/post.js
import shortId from "shortid";
import produce from "immer";
import faker from "faker";
export const initialState = {
mainPosts: [],
imagePaths: [],
hasMorePost: true,
loadPostsLoading: false,
loadPostsDone: false,
loadPostsError: null,
addPostLoading: false,
addPostDone: false,
addPostError: null,
removePostLoading: false,
removePostDone: false,
removePostError: null,
addCommentLoading: false,
addCommentDone: false,
addCommentError: 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.image(),
},
],
Comments: [
{
User: {
id: shortId.generate(),
nickname: faker.name.findName(),
},
content: faker.lorem.sentence(),
},
],
}));
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,
});
export const addComment = (data) => ({
type: ADD_COMMENT_REQUEST,
data,
});
const dummyPost = (data) => ({
id: data.id,
content: data.content,
User: {
id: 1,
nickname: "은짱",
},
Images: [],
Comments: [],
});
const dummyComment = (data) => ({
id: shortId.generate(),
content: data,
User: {
id: 1,
nickname: "은짱",
},
});
//reducer는 이전 상태를 액션을 통해 다음 상태로 만들어내는 함수(불변성은 ㅣ키면서)
const reducer = (state = initialState, action) => {
return produce(state, (draft) => {
switch (action.type) {
case LOAD_POSTS_REQUEST:
draft.loadPostsLoading = true;
draft.loadPostsDone = false;
draft.loadPostsError = null;
break;
case LOAD_POSTS_SUCCESS:
draft.loadPostsLoading = false;
draft.loadPostsDone = true;
draft.mainPosts = draft.mainPosts.concat(action.data);
draft.hasMorePost = draft.mainPosts.length < 50;
break;
case LOAD_POSTS_FAILURE:
draft.loadPostsLoading = false;
draft.loadPostsError = 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;
## saga/post.js
import axios from "axios";
import {
delay,
put,
takeLatest,
all,
fork,
throttle,
} from "redux-saga/effects";
import shortId, { generate } from "shortid";
import {
ADD_COMMENT_FAILURE,
ADD_COMMENT_REQUEST,
ADD_COMMENT_SUCCESS,
ADD_POST_FAILURE,
ADD_POST_REQUEST,
ADD_POST_SUCCESS,
generateDummyPost,
LOAD_POSTS_FAILURE,
LOAD_POSTS_REQUEST,
LOAD_POSTS_SUCCESS,
REMOVE_POST_FAILURE,
REMOVE_POST_REQUEST,
REMOVE_POST_SUCCESS,
} from "../reducers/post";
import { ADD_POST_TO_ME, REMOVE_POST_OF_ME } from "../reducers/user";
function addPostAPI(data) {
return axios.post("/api/post", data);
}
function* addPost(action) {
try {
// const result = yield call(addPostAPI, action.data);
yield delay(1000);
const id = shortId.generate();
yield put({
type: ADD_POST_SUCCESS,
data: {
id,
content: action.data,
},
// data: result.data,
});
yield put({
type: ADD_POST_TO_ME,
data: id,
});
} catch (err) {
yield put({
type: ADD_POST_FAILURE,
data: err.response.data,
});
}
}
function loadPostsAPI(data) {
return axios.get("/api/posts", data);
}
function* loadPosts(action) {
try {
// const result = yield call(loadPostsAPI, action.data);
yield delay(1000);
yield put({
type: LOAD_POSTS_SUCCESS,
data: generateDummyPost(10),
// data: result.data,
});
} catch (err) {
yield put({
type: LOAD_POSTS_FAILURE,
data: err.response.data,
});
}
}
function removePostAPI(data) {
return axios.post("/api/post", data);
}
function* removePost(action) {
try {
// const result = yield call(removePostAPI, action.data);
yield delay(1000);
yield put({
type: REMOVE_POST_SUCCESS,
data: action.data,
// data: result.data,
});
yield put({
type: REMOVE_POST_OF_ME,
data: action.data,
});
} catch (err) {
yield put({
type: REMOVE_POST_FAILURE,
data: err.response.data,
});
}
}
function addCommentAPI(data) {
return axios.post(`/api/post/${data.postId}/comment`, data);
}
function* addComment(action) {
try {
// const result = yield call(addCommentAPI, action.data);
yield delay(1000);
yield put({
type: ADD_COMMENT_SUCCESS,
data: action.data,
// data: result.data,
});
} catch (err) {
yield put({
type: ADD_COMMENT_FAILURE,
data: err.response.data,
});
}
}
function* watchAddPost() {
yield takeLatest(ADD_POST_REQUEST, addPost);
}
function* watchLoadPosts() {
yield throttle(5000, LOAD_POSTS_REQUEST, loadPosts);
}
function* watchRemovePost() {
yield takeLatest(REMOVE_POST_REQUEST, removePost);
}
function* watchAddComment() {
yield takeLatest(ADD_COMMENT_REQUEST, addComment);
}
export default function* postSaga() {
yield all([
fork(watchAddPost),
fork(watchLoadPosts),
fork(watchRemovePost),
fork(watchAddComment),
]);
}
답변을 작성해보세요.
0
답변 1