import { all, fork, call, put, take } from 'redux-saga/effects';
import axios from 'axios';
function logInAPI() {
// Generator가 아니므로 * 붙이면 안 된다.
return axios.post('/api/login')
}
// 요청이 성공/실패 할 수 있으므로 try-catch
function* logIn() {
try {
const result = yield call(logInAPI) // 결과값을 받는다.
axios.post('/api/login')
.then((result) => {
// 결과를 받아서
yield put({
type: 'LOG_IN_SUCCESS',
data: result.data
});
});
} catch (err) {
yield put({
type: 'LOG_IN_FAILURE',
data: err.response.data
});
}
}
function* watchLogIn() {
// LOG_IN이라는 액션이 실행될 때까지 기다리겠다. (EventListener 역할)
yield take('LOG_IN_REQUEST', logIn);
}
function* watchLogOut() {
yield take('LOG_OUT_REQUEST');
}
function* watchAddPost() {
yield take('ADD_POST_REQUEST');
}
export default function* rootSaga() {
// 배열 안에 것들을 모두 실행시켜준다.
// fork : 함수 실행
// fork / call은 Generator 기능이지만 서로 다른 것이다. (명확한 이해 필요)
yield all([
fork(watchLogin),
fork(watchLogOut),
fork(watchAddPost),
]);
}
// put : 액션을 Dispatch
자, 그러면 굳이 call과 yield를 쓰는 이유는 무엇일까?
그 이유는 redux-saga가 테스트 할때 yield 특성으로 인해 편리하기 때문이다.
generator를 쓰면 yield가 있는 곳마다 한 줄 한 줄 실행하며 돌려볼 수 있게 때문에
매우 편리하다.
Take의 특성
한 번 사용하면 사라져버린다.
function* watchLogIn() {
// LOG_IN이라는 액션이 실행될 때까지 기다리겠다. (EventListener 역할)
yield take('LOG_IN_REQUEST', logIn);
}
function* watchLogOut() {
yield take('LOG_OUT_REQUEST', logOut);
}
function* watchAddPost() {
yield take('ADD_POST_REQUEST', addPost);
}
이것을 해결하는 방법은?
function* watchLogIn() {
// LOG_IN이라는 액션이 실행될 때까지 기다리겠다. (EventListener 역할)
while (true) {
yield take('LOG_IN_REQUEST', logIn);
}
}
function* watchLogOut() {
while (true) {
yield take('LOG_OUT_REQUEST', logOut);
}
}
function* watchAddPost() {
while (true) {
yield take('ADD_POST_REQUEST', addPost);
}
}
while로 감싸준다.
그러면 진정한 EventListener처럼 구동된다.
* while take는 동기적으로 동작하지만,
takeEvery는 비동기로 동작한다.
But, While문으로 계속 감싸주면 가독성도 좋지 않고
코드 라인 수가 늘어난다.
이 부분을 극복하기 위해 나온 이펙트가
'takeEvery'이다.
function* watchLogIn() {
// LOG_IN이라는 액션이 실행될 때까지 기다리겠다. (EventListener 역할)
yield takeEvery('LOG_IN_REQUEST', logIn);
}
function* watchLogOut() {
yield takeEvery('LOG_OUT_REQUEST', logOut);
}
function* watchAddPost() {
yield takeEvery('ADD_POST_REQUEST', addPost);
}
이 외에도
takeLatest
클릭 두 번 했을 때 처리.
버튼을 두 번 클릭 했을 때, takeEvery의 경우 2번 호출된다.
그러나, takeLatest로 처리하게 되면 마지막것만 처리된다.
100번을 클릭해도 앞에 99개는 무시되고 마지막 1개만 처리된다.
하지만 무조건적이지는 않다.
예외로 이미 완료됐다면 그것은 완료된 채로 놔두고,
그 다음에 실행된다.
앞에 것도 로딩중이고 뒤에 것도 로딩중일 경우
완료되지 않은 것이 있다면 그 때 구동된다.
< 치명적인 단점 >
front에서만 그렇게 생각하는 것이다.
server에서는 n번 요청이 가는 것이다.
(새로고침할 때 나타남...)
takeLeading
첫 번째 클릭만 실행.
throttle
function* watchAddPost() {
yield throttle('ADD_POST_REQUEST', addPost, 10000);
}
2초로 설정해놓는다면,
2초동안 딱 한 번만 실행하는 것이다.
'개발 > React.js' 카테고리의 다른 글
한 입 크기로 잘라먹는 리액트 Chapter 5. 리액트의 기본 기능(1) (0) | 2023.10.17 |
---|---|
[React-Native] warn Multiple Podfiles were found 에러, Looks like your iOS environment is not properly set 에러 해결 (0) | 2022.11.27 |
[React.js] Redux-saga Generator 개념 (0) | 2022.11.16 |
[React.js] Redux-thunk란? && Custom Middleware (0) | 2022.11.16 |
[React.js] Reducer - index.js prev ver. [zerocho님 강의] (0) | 2022.11.16 |