어제부터 4주 프로젝트에서 구현한 모달창을 리팩토링하기위해 redux middlware를 로컬에서 적용해보고 있다.
목표: 모달창의 예/아니오에 따른 콜백함수를 리덕스에 전달하여 실행시키기
현재는 Modal component에 콜백함수를 직접 넣어서 예/아니오에 따라 실행시키고 있는데 기능은 어찌저찌 되지만...
Modal component에 온갖 콜백함수가 들어가게되고 컴포넌트가 너무 무거워진다는 생각이 들었다. 공부를 좀 하다가 middleware를 써서 함수를 dispatch하면 되겠다는 생각이 들었다.
redux-toolkit
을 사용했기때문에 기본으로 내장되어있는 redux-thunk
를 먼저 사용해봤다.
export const modalCallback = createAsyncThunk('modal/callback', async (callback: any, thunkApi) => {
const state = thunkApi.getState() as RootState;
if (!state.modal.open) {
console.log('되라되라');
}
return {
payload: await callback(),
};
});
export const modalSlice = createSlice({
name: 'modal',
initialState,
reducers: {
...
},
extraReducers: {
[modalCallback.pending.type]: (state) => {
console.log('pending');
},
[modalCallback.fulfilled.type]: (state, action: PayloadAction<OpenPayload>) => {
console.log('fulfilled:::');
},
[modalCallback.rejected.type]: (state) => {
console.log('rejected');
},
},
});
콜백함수를 dispatch하고 미들웨어를 통해 실행시키는 건 잘되지만 예/아니오 를 눌러서 상태가 변했을 때 실행시키는 것, 즉 store를 구독해서 실행시키는 방법을 찾지 못했다.thunkApi.getState
로 state에 접근해서 어떻게 해볼까 했지만 state를 읽는 건 가능했지만 state의 변화에따라 다시 modalCallback을 실행시키는 방법은 찾지 못했다. ㅠㅠ
구글링구글링 계속하다가 다음 정보를 알아냈다.
thunk는 절대로 action에 응답을 줄수 없다. 반면 saga는 store를 구독하고 특정 작업이 디스패치될때 saga가 실행되도록 할 수 있다.
ㅇ0ㅇ
saga를 써보기로 했다.
saga는 ES6문법인 generator를 사용하기때문에 이 공부가 먼저 선행되어야 할 것 같아서 정리겸 적어본다.🤸🏻
Generator
- 제너레이터는 함수의 실행을 중간에 멈췄다가 재개할 수 있는 독특한 문법이다.
- function 옆에 * 을 써서 만들고, 내부에 yield 키워드를 사용한다.
- yield 에서 함수의 실행을 멈출 수 있다.
예시코드
function* fn() {
console.log(1);
yield 1;
console.log(2);
yield 2;
console.log(3);
console.log(4);
yield 3;
return "finish"
}
const generator = fn();
next()
는 다음 yield에 도달할때까지의 코드를 실행시킨다.value
는 yield 오른쪽 값을 나타내고 done
은 함수 실행이 완료됐는지를 boolean
으로 나타낸다.
Generator의 3가지 메소드
Generator는 3가지 메소드를 갖고있다.
next
: 다음 yield 값을 반환한다.return
: 주어진 값을 반환하고 생성기를 종료한다.throw
: 생성기로 에러를 throw한다.
next()에 인수 전달하기
generator에 외부값을 넣을 수도 있다.
function* fn() {
const num1 = yield "첫번째 숫자를 입력해주세요";
console.log(num1);
const num2 = yield "두번째 숫자를 입력해주세요";
console.log(num2);
return num1 + num2;
}
const generator = fn();
yield를 변수에 할당한 다음에, next()
에 인자를 넣으면 해당 변수에 값이 할당된다.
Generator는 값을 미리 만들어 놓지 않는다.
필요한 순간에만 연산해서 값을 주기때문에 메모리 관리 측면에서 효율적이다.
이같은 특성때문에 아래와 같은 코드도 가능하다.
function* fn() {
let index = 0;
while(true){
yield index++;
}
}
const generator = fn();
무한 반복코드를 만들어도 브라우저가 꺼지지 않는다. 메소드로 호출할때만 값을 주기 때문이다.
generator를 사용하면 쓸지 안쓸지 모르는 값들을 메모리에 저장할 필요없이 필요할 때만 값을 호출할 수 있다.
yield*을 이용해서 다른 generator 불러오기
function* gen1() {
yield "W";
yield "O";
yield "R";
yield "L";
yield "D";
}
function* gen2() {
yield "Hello,";
yield* gen1();
yield "!";
}
const generator = gen2()
+) spread syntax를 사용해서 done이 true가 될때까지 값을 펼쳐줄 수 있다.
+) yield*에서 *을 빼면 generator 객체가 출력된다.
아직 눈과 손에 익숙하지는 않지만
saga를 쓰려고 이리지리 하다보면 금방 익숙해질 것 같다.
'개인공부 > TIL(Today I Learned)' 카테고리의 다른 글
모달창 리팩토링하기 (with Redux-saga) (0) | 2021.07.15 |
---|---|
TIL 93일차_Mongoose 사용하기 (0) | 2021.04.21 |
TIL 92일차_Null Check (0) | 2021.04.20 |
TIL 91일차_axios에서의 오류처리 (0) | 2021.04.19 |
TIL 90일차_jwt 사용하기 (0) | 2021.04.18 |