인프런 커뮤니티 질문&답변
ADD_COMMENT_SUCCESS acrtion이 실행되지 않는 질문드립니다.
해결된 질문
작성
·
437
0
ADD_COMMENT_REQUEST action은 아래와 같이 정상적으로 data도 전달하고 동작하는데
ADD_COMMENT_SUCCESS action이 실행되면 아래와 같은 오류가 발생해서 action이 실행되지 않는건 물론이고 다른 action도 동작하지 않는 문제가 발생해서 질문드립니다.
// action 발생 컴포넌트
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { Button, Form, Input, Row } from 'antd';
import { useSelector, useDispatch } from 'react-redux';
import { addCommentRequestAction } from '../../reducers/post';
const CommentForm = ({ mainPosts }) => {
const dispatch = useDispatch();
const { addCommentLoading } = useSelector((state) => state.post);
const id = useSelector((state) => state.user.me?.id);
const [form] = Form.useForm();
const onSubmitComment = useCallback((value) => {
console.log(value.comment, mainPosts.id, id);
dispatch(addCommentRequestAction({commentText: value.comment, postId: mainPosts.id, userId: id}));
form.resetFields();
}, []);
return (
<>
<Form
form={form}
name="writeComment"
onFinish={onSubmitComment}
>
<Form.Item
name="comment"
rules={[
{
type: 'text',
},
]}
>
<Input.TextArea
placeholder='댓글을 입력하세요.'
showCount
maxLength={100}
rows={2}
/>
</Form.Item>
<Row align='end'>
<Button
type='primary'
htmlType='submit'
loading={addCommentLoading}
>
등록
</Button>
</Row>
</Form>
</>
)
};
CommentForm.propTypes = {
mainPosts: PropTypes.shape({
id: PropTypes.string,
User: PropTypes.object,
title: PropTypes.string,
desc: PropTypes.string,
content: PropTypes.arrayOf(PropTypes.object),
Images: PropTypes.arrayOf(PropTypes.object),
tag: PropTypes.string,
Comments: PropTypes.arrayOf(PropTypes.object),
})
};
export default CommentForm;
// reducers/post.js
import produce from 'immer';
import shortId from 'shortid';
export const initialState = {
mainPosts: [{
id: 1,
User: {
id: 1,
nickname: 'ZeroCho'
},
title: '돼지고기 갈비찜',
desc: '한국인이 좋아하는 대표 고기 요리 갈비찜 레시피!!',
content: [{
ingredient: '주 재료 = 갈비 600g, 당근 20g, 은행 10알, 밤 10개, 파 1대, 양파 50g, 양념장 재료 = 간장 3큰술, 설탕 2큰술, 육수 12큰술, 다진 생강 1작은술, 깨소금 2큰술, 청주 ¼컵, 다진 마늘 3큰술, 참기름 1큰술, 후춧가루 약간',
}, {
recipes: '갈비는 사방 5㎝ 크기로 썰어 기름기를 제거한다., 기름기를 없앤 갈빗살에 칼집을 낸 다음 찬물에 30분~한 시간쯤 담가 핏물을 빼주고, 혹시 모를 절단 과정에서 섞인 뼛가루나 뼛조각을 제거해준다. 이 핏물 빼는 과정을 속성으로 하고 싶으면, 한 번 끓여 데치는 거로 대체해도 되긴 된다, 끓는 물에 핏물을 뺀 갈비와 토막 낸 양파·파를 넣어 속까지 익을 때까지 삶아낸다. 중간에 젓가락으로 고기를 찔러보아 핏물이 나오는지 확인한다. 핏물이 나오면 고기가 덜 익은 것., 고기가 익으면 체에 받친다. 이 국물은 걸러서 지저분한 것을 제거하고 양념장의 육수로 이용한다. 갈비는 사방 5㎝ 크기로 썰어 기름기를 제거한다., 기름기를 없앤 갈빗살에 칼집을 낸 다음 찬물에 30분~한 시간쯤 담가 핏물을 빼주고, 혹시 모를 절단 과정에서 섞인 뼛가루나 뼛조각을 제거해준다. 이 핏물 빼는 과정을 속성으로 하고 싶으면, 한 번 끓여 데치는 거로 대체해도 되긴 된다, 끓는 물에 핏물을 뺀 갈비와 토막 낸 양파·파를 넣어 속까지 익을 때까지 삶아낸다. 중간에 젓가락으로 고기를 찔러보아 핏물이 나오는지 확인한다. 핏물이 나오면 고기가 덜 익은 것., 고기가 익으면 체에 받친다. 이 국물은 걸러서 지저분한 것을 제거하고 양념장의 육수로 이용한다.'
}, {
tips: '갈비를 한 번 끓여서 핏물이나 기름기를 어느 정도 빼준 후, 재료들을 압력밥솥에 싹 때려넣고 그대로 푹 익혀버리면 질긴 고기가 녹아드는 수준이 되어 부드럽게 먹을 수 있다.'
}],
Images: [{
src: 'https://recipe1.ezmember.co.kr/cache/recipe/2015/06/03/f6551b241deba537266c7dfe668e09821.jpg',
}, {
src: 'https://recipe1.ezmember.co.kr/cache/recipe/2017/09/15/af5ed61b01ce6d0c8ded20d59f0d15e31.jpg',
}, {
src: 'https://www.cj.co.kr/images/theKitchen/PHON/0000002320/0000009726/0000002320.jpg',
}],
tag: '맛있을것같아요 #hashtag1 짱짱맨!! #hashtag2 ##hashtag3',
Comments: [{
User: {
nickname: 'AppleLover',
},
content: '우와 정말 맛있을것 같아요 ㅎㅎ',
}, {
User: {
nickname: 'Nightmare',
},
content: '오늘 저녁은 갈비찜이다!!',
}]
}],
imagePaths: [],
addPostLoading: false,
addPostDone: false,
addPostError: null,
addCommentLoading: false,
addCommentDone: false,
addCommentError: null,
};
const dummyPost = (data) => ({
id: shortId.generate(),
User: {
id: 2,
nickname: 'Mirrer',
},
title: data.title,
desc: data.desc,
content: [{
ingredient: data.ingredient,
}, {
recipes: data.recipes,
}, {
tips: data.tips,
}],
tag: data.tags,
Images: [{
src: 'https://www.hongcheon.go.kr/site/tour/images/contents/cts1927_img1.jpg'
}, {
src: 'https://t1.daumcdn.net/cfile/tistory/1837BE1A4BF1BA073F'
}],
Comments: [{
User: {
nickname: 'Korean',
},
content: '역시 한국인은 밥심이죠 ㅎㅎ',
}],
});
const dummyComment = (data) => ({
User: {
id: 2,
nickname: 'Mirrer',
},
content: data,
});
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 addPostRequestAction = (data) => {
console.log('reducer');
return {
type: ADD_POST_REQUEST,
data,
}
};
export const addCommentRequestAction = (data) => {
console.log('reducer');
return {
type: ADD_COMMENT_REQUEST,
data,
}
};
const reducer = (state = initialState, action) => {
return produce(state, (draft) => {
switch (action.type) {
case ADD_POST_REQUEST:
draft.addPostLoading = true;
draft.addPostDone = false;
draft.addPostError = null;
break;
case ADD_POST_SUCCESS:
draft.mainPosts.unshift(dummyPost(action.data));
draft.addPostLoading = false;
draft.addPostDone = true;
break;
case ADD_POST_FAILURE:
draft.addPostLoading = false;
draft.addPostError = action.error;
break;
case ADD_COMMENT_REQUEST:
draft.addCommentLoading = true;
draft.addCommentDone = false;
draft.addCommentError = null;
break;
case ADD_COMMENT_SUCCESS: {
const post = mainPosts.find((v) => v.id === action.data.postId);
post.Comments.unshift(dummyComment(action.data.commentText));
draft.addCommentLoading = false;
draft.addCommentDone = true;
break;
}
case ADD_COMMENT_FAILURE:
draft.addCommentLoading = false;
draft.addCommentError = action.error;
break;
default:
return state;
}
});
};
export default reducer;
// sagas/post.js
import { all, fork, delay, put, takeLatest } from 'redux-saga/effects';
// import axios from 'axios';
import {
ADD_POST_REQUEST, ADD_POST_SUCCESS, ADD_POST_FAILURE,
ADD_COMMENT_REQUEST, ADD_COMMENT_SUCCESS, ADD_COMMENT_FAILURE
} from '../reducers/post';
// function addPostAPI(data) {
// return axios.post('/api/post', data);
// }
function* addPost(action) {
try {
// const result = yield call(addPostAPI, action.data);
yield delay(1000);
yield put({
type: ADD_POST_SUCCESS,
data: action.data,
})
} catch(err) {
yield put({
type: ADD_POST_FAILURE,
data: err.response.data
})
}
}
// function addCommentAPI(data) {
// return axios.post(`/api/post/${data.postId}/comment`, data);
// }
function* addComment(action) {
console.log(action);
try {
// const result = yield call(addCommentAPI, action.data);
yield delay(1000);
yield put({
type: ADD_COMMENT_SUCCESS,
data: action.data,
})
} catch(err) {
yield put({
type: ADD_COMMENT_FAILURE,
data: err.response.data
})
}
}
function* watchAddPost() {
yield takeLatest(ADD_POST_REQUEST, addPost);
}
function* watchAddComment() {
yield takeLatest(ADD_COMMENT_REQUEST, addComment);
}
export default function* postSaga() {
yield all([
fork(watchAddPost),
fork(watchAddComment),
]);
}
.png)
.png)
.png)
답변 1
0
function* addComment 안에서 action 콘솔로그 찍은 것 어떻게 나오시나요? 여기에 action이 Undefined라고 되어있는데 dispatch(액션)의 액션이 그대로 전달되어야 합니다.
아, 저 data가 err.response.data의 data같은데요. 에러가 난 위치를 파악하셔야 합니다. 저기 addComment$ 옆에 위치 나오니까 눌러보시면 됩니다. err.response.data에서 에러난 것이면 서버에서 에러난 것이라 서버쪽 로그 보셔야 합니다.
서버에서 발생한 에러이군요 ㅜㅜ
서버쪽 관련해서는 아직 학습하지 않아서 무지한상태여서 걱정이네요
이런 질문드리는게 안좋은 방법이여서 죄송한데 혹시 이 문제에 대해서 해결책을 알 수 있을까요
전체 오류의 콘솔내역과 말씀해주신 addComment$ 옆에 위치를 클릭했을때 화면은 아래와 같습니다


문제를 혼자 해결해보려고 했는데 구글링하고 비슷한 오류를 찾아봐도 방법을 못찾았습니다ㅜㅜ
콘솔에 발생한 에러를 클릭해보니 아래와 같은 내역이 나왔습니다.
첫번쨰 에러 내역입니다.
.png)
post.js?98c0:47 saga addComment1
post.js?98c0:50 saga addComment2
next-dev.js?3515:25 TypeError: Cannot read properties of undefined (reading 'data')
at addComment$ (post.js?98c0:59:26)
at tryCatch (runtime.js?ecd4:45:16)
at Generator.invoke [as _invoke] (runtime.js?ecd4:274:1)
at prototype.<computed> [as throw] (runtime.js?ecd4:97:1)
at next (redux-saga-core.esm.js?af2c:1126:1)
at currCb (redux-saga-core.esm.js?af2c:1251:1)
at eval (redux-saga-core.esm.js?af2c:474:1)
at exec (redux-saga-core.esm.js?af2c:31:1)
at flush (redux-saga-core.esm.js?af2c:87:1)
at asap (redux-saga-core.esm.js?af2c:46:1)
at runPutEffect (redux-saga-core.esm.js?af2c:468:1)
at runEffect (redux-saga-core.esm.js?af2c:1204:1)
at digestEffect (redux-saga-core.esm.js?af2c:1271:1)
at next (redux-saga-core.esm.js?af2c:1161:1)
at currCb (redux-saga-core.esm.js?af2c:1251:1)
window.console.error @ next-dev.js?3515:25
logError @ io-6de156f3.js?bd36:111
end @ redux-saga-core.esm.js?af2c:1003
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
next @ redux-saga-core.esm.js?af2c:1178
currCb @ redux-saga-core.esm.js?af2c:1251
eval @ redux-saga-core.esm.js?af2c:474
exec @ redux-saga-core.esm.js?af2c:31
flush @ redux-saga-core.esm.js?af2c:87
asap @ redux-saga-core.esm.js?af2c:46
runPutEffect @ redux-saga-core.esm.js?af2c:468
runEffect @ redux-saga-core.esm.js?af2c:1204
digestEffect @ redux-saga-core.esm.js?af2c:1271
next @ redux-saga-core.esm.js?af2c:1161
currCb @ redux-saga-core.esm.js?af2c:1251
Promise.then (async)
resolvePromise @ redux-saga-core.esm.js?af2c:395
runCallEffect @ redux-saga-core.esm.js?af2c:527
runEffect @ redux-saga-core.esm.js?af2c:1204
digestEffect @ redux-saga-core.esm.js?af2c:1271
next @ redux-saga-core.esm.js?af2c:1161
proc @ redux-saga-core.esm.js?af2c:1108
eval @ redux-saga-core.esm.js?af2c:585
immediately @ redux-saga-core.esm.js?af2c:56
runForkEffect @ redux-saga-core.esm.js?af2c:584
runEffect @ redux-saga-core.esm.js?af2c:1204
digestEffect @ redux-saga-core.esm.js?af2c:1271
next @ redux-saga-core.esm.js?af2c:1161
currCb @ redux-saga-core.esm.js?af2c:1251
takeCb @ redux-saga-core.esm.js?af2c:503
put @ redux-saga-core.esm.js?af2c:339
eval @ redux-saga-core.esm.js?af2c:376
exec @ redux-saga-core.esm.js?af2c:31
flush @ redux-saga-core.esm.js?af2c:87
asap @ redux-saga-core.esm.js?af2c:46
chan.put @ redux-saga-core.esm.js?af2c:375
eval @ redux-saga-core.esm.js?af2c:1412
dispatch @ VM11095:3665
eval @ CommentForm.js?29fe:16
onFinish @ Form.js?e075:75
eval @ useForm.js?3ca7:931
Promise.then (async)
FormStore.submit @ useForm.js?3ca7:926
onSubmit @ Form.js?e075:132
callCallback @ react-dom.development.js?ac89:4164
invokeGuardedCallbackDev @ react-dom.development.js?ac89:4213
invokeGuardedCallback @ react-dom.development.js?ac89:4277
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js?ac89:4291
executeDispatch @ react-dom.development.js?ac89:9041
processDispatchQueueItemsInOrder @ react-dom.development.js?ac89:9073
processDispatchQueue @ react-dom.development.js?ac89:9086
dispatchEventsForPlugins @ react-dom.development.js?ac89:9097
eval @ react-dom.development.js?ac89:9288
batchedUpdates$1 @ react-dom.development.js?ac89:26140
batchedUpdates @ react-dom.development.js?ac89:3991
dispatchEventForPluginEventSystem @ react-dom.development.js?ac89:9287
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js?ac89:6465
dispatchEvent @ react-dom.development.js?ac89:6457
dispatchDiscreteEvent @ react-dom.development.js?ac89:6430
두번째 에러로그입니다.
.png)
next-dev.js?3515:25 The above error occurred in task addComment
created by takeLatest(ADD_COMMENT_REQUEST, addComment)
created by watchAddComment
created by postSaga
created by rootSaga
Tasks cancelled due to error:
takeLatest(ADD_COMMENT_REQUEST, addComment)
watchAddPost
userSaga
window.console.error @ next-dev.js?3515:25
logError @ io-6de156f3.js?bd36:112
end @ redux-saga-core.esm.js?af2c:1003
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
end @ redux-saga-core.esm.js?af2c:1012
abort @ redux-saga-core.esm.js?af2c:813
task.cont @ redux-saga-core.esm.js?af2c:828
next @ redux-saga-core.esm.js?af2c:1178
currCb @ redux-saga-core.esm.js?af2c:1251
eval @ redux-saga-core.esm.js?af2c:474
exec @ redux-saga-core.esm.js?af2c:31
flush @ redux-saga-core.esm.js?af2c:87
asap @ redux-saga-core.esm.js?af2c:46
runPutEffect @ redux-saga-core.esm.js?af2c:468
runEffect @ redux-saga-core.esm.js?af2c:1204
digestEffect @ redux-saga-core.esm.js?af2c:1271
next @ redux-saga-core.esm.js?af2c:1161
currCb @ redux-saga-core.esm.js?af2c:1251
Promise.then (async)
resolvePromise @ redux-saga-core.esm.js?af2c:395
runCallEffect @ redux-saga-core.esm.js?af2c:527
runEffect @ redux-saga-core.esm.js?af2c:1204
digestEffect @ redux-saga-core.esm.js?af2c:1271
next @ redux-saga-core.esm.js?af2c:1161
proc @ redux-saga-core.esm.js?af2c:1108
eval @ redux-saga-core.esm.js?af2c:585
immediately @ redux-saga-core.esm.js?af2c:56
runForkEffect @ redux-saga-core.esm.js?af2c:584
runEffect @ redux-saga-core.esm.js?af2c:1204
digestEffect @ redux-saga-core.esm.js?af2c:1271
next @ redux-saga-core.esm.js?af2c:1161
currCb @ redux-saga-core.esm.js?af2c:1251
takeCb @ redux-saga-core.esm.js?af2c:503
put @ redux-saga-core.esm.js?af2c:339
eval @ redux-saga-core.esm.js?af2c:376
exec @ redux-saga-core.esm.js?af2c:31
flush @ redux-saga-core.esm.js?af2c:87
asap @ redux-saga-core.esm.js?af2c:46
chan.put @ redux-saga-core.esm.js?af2c:375
eval @ redux-saga-core.esm.js?af2c:1412
dispatch @ VM11095:3665
eval @ CommentForm.js?29fe:16
onFinish @ Form.js?e075:75
eval @ useForm.js?3ca7:931
Promise.then (async)
FormStore.submit @ useForm.js?3ca7:926
onSubmit @ Form.js?e075:132
callCallback @ react-dom.development.js?ac89:4164
invokeGuardedCallbackDev @ react-dom.development.js?ac89:4213
invokeGuardedCallback @ react-dom.development.js?ac89:4277
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js?ac89:4291
executeDispatch @ react-dom.development.js?ac89:9041
processDispatchQueueItemsInOrder @ react-dom.development.js?ac89:9073
processDispatchQueue @ react-dom.development.js?ac89:9086
dispatchEventsForPlugins @ react-dom.development.js?ac89:9097
eval @ react-dom.development.js?ac89:9288
batchedUpdates$1 @ react-dom.development.js?ac89:26140
batchedUpdates @ react-dom.development.js?ac89:3991
dispatchEventForPluginEventSystem @ react-dom.development.js?ac89:9287
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js?ac89:6465
dispatchEvent @ react-dom.development.js?ac89:6457
dispatchDiscreteEvent @ react-dom.development.js?ac89:6430
어.. 아직 백엔드 서버 실습 아예 안 하신 상태인가요? 서버쪽 에러라고 수긍하셔서 서버쪽 에러인 줄 알았네요. 백엔드 서버 아예 안 만드셨으면 서버에서 에러가 날 리가 없죠...
reducer에서 ADD_COMMENT_SUCCESS 쪽 에러겠네요 그러면. 보니까 draft.mainPosts 안 하고 그냥 바로 mainPosts 변수 선언 없이 사용하셨네요.
네ㅜㅜ 아직 백엔드 강의는 듣지 않은상태입니다.
제가 질문할때 미리 말씀드렸어야했는데 애매하게 질문드린것 같네요 죄송합니다.
오류는 말씀해주신대로 draft.mainPosts를 사용하니 해결되었습니다 감사합니다!!
근데 추가로 궁금한 점이 있습니다.
1. 코드를 빌드한 상태에서 reducer, saga의 코드를 수정하면 핫리로딩이 적용안되서 빌드를 껐다 다시 재실행하는데 원래 이런건가요? 아니면 제 pc사양문제일까요?
2. ADD_COMMENT_REQUEST에서 오류가 발생했을 때 다른 action들도 동작하지 않았는데 어떠한 이유때문에 이렇게 동작했던걸까요?
답변해주시면 감사하겠습니다
1. 리덕스와 사가쪽은 핫 리로딩은 안 돼서 브라우저를 새로고침해야 합니다. 자동으로 새로고침해주지 않나요? 빌드를 껐다 재실행한다는 건 무슨 말씀이신지 모르겠습니다. 직접 빌드를 끄셨다는 말씀인가요?
2. 다른 action들이 동작하지 않았다고 하셨는데 밑에서는 뭐가 동작했다고 하신 건가요..? ADD_POST_REQUEST 같은 애들은 동작할텐데요?
1. 코드를 수정하고 브라우저에서 새로고침을 누르면 됬군요. 리덕스와 사가의 코드를 수정할때마다 에디터 터미널에서 컨트롤 + c 한 뒤 다시 npm run dev를 해서 실행해서 결과를 확인했습니다 ㅜㅜ
2. 크롬 redux확장프로그램을 확인했을때 ADD_COMMENT_REQUEST이후에 다른 action을 실행했었는데 REQUEST까지만 동작을 하고 이후에 SUCCESS, FAILURE로 넘어가질 않았습니다!!





바쁘신데 답변 감사합니다
코드를 수정하고 실행한 결과 아래와같이 콘솔은 정상적으로 출력되고 이 후 오류가발생하는데
ADD_COMMENT_SUCCESS action이 실행되면서 같이 전달되는 data가 문제가 있어서 오류가 발생하는걸까요?