React-Saga에서 95%의 비동기 요청은 다음과 같은 패턴으로 작성해도 무방하다.
import { all, fork, call, put, takeLatest } from 'redux-saga/effects';
import { LOG_IN_REQUEST, LOG_IN_SUCCESS, LOG_IN_FAILURE } from '../reducers/user';
function* login() { // 3. 실제 동작할 코드는 따로 작성
try {
yield fork(logger);
yield call(loginAPI);
yield put({
type: LOG_IN_SUCCESS,
});
} catch (e) {
console.error(e);
yield put({
type: LOG_IN_FAILURE,
});
}
}
function* watchLogin() {
yield takeLatest(LOG_IN_REQUEST, login);
// 2. takeLatest 또는 takeEvery 둘 중 무엇을 쓸 지 결정하고,
// 실제 동작 할 login은 따로 작성
}
export default function* userSaga() {
yield all([fork(watchLogin)]); // 1. Saga에 watchLogin을 등록하고
}
컴포넌트에서 dispatch
할 때 action
뿐 만 아니라 데이터도 saga에 넣어줄 수 있습니다.
import React, { useCallback } from 'react';
import { useSelector } from 'react-redux';
const PostCard = ({ post }) => {
const { me } = useSelector(state => state.user);
const dispatch = useDispatch();
const onSubmitComment = useCallback(() => {
if (!me) {
return alert('로그인이 필요합니다.');
}
dispatch({
type: ADD_COMMENT_REQUEST,
data: { // dispatch할 때 saga에 데이터를 전달할 수 있습니다.
postId: post.id,
},
});
}, []);
return (
<div>
{commentFormOpened && (
<>
<Form onFinish={onSubmitComment}>
<Form.Item>
<Input.TextArea
rows={4}
value={commentText}
onChange={onChangeCommentText}
/>
</Form.Item>
<Button type='primary' htmlType='submit'>
삐약
</Button>
</Form>
</>
)}
</div>
);
};
function addCommentAPI(addCommentData) {
// yield call(addCommentAPI, action.data)
// 의 두 번째 인자 action.data가 addCommentData 인자로 들어갑니다.
// 서버에 요청 보내는 부분
}
function* addComment(action) { // action 인자를 통해
// ADD_COMMENT_REQUEST dispatch에 있는 data를 조회할 수 있습니다.
try {
yield call(addCommentAPI, action.data); // 두 번째 인자에 들어가는 action.data 데이터는
yield put({
type: ADD_COMMENT_SUCCESS,
data: {
postId: action.data.postId, // ADD_COMMENT_REQUEST dispatch에 포함된 data 조회. -> ADD_COMMENT_SUCCESS 액션에 동봉하여 dispatch 합니다.
},
});
} catch (e) {
console.error(e);
put({
type: ADD_COMMENT_FAILURE,
error: e,
});
}
}
function* watchAddComment() { // ADD_COMMENT_REQUEST 액션이 dispatch 되면
yield takeLatest(ADD_COMMENT_REQUEST, addComment); // addComment 함수 실행
}
export default function* postSaga() {
yield all([fork(watchAddPost), fork(watchAddComment)]);
}