redux thunk 이해하기
사용해보기
redux에서 middleware를 사용해 비동기 처리를 하기 위해서는 어떤 과정을 거치면 될까?
그보다 어떤것을 비동기 처리해야 하는지부터 알아보자.
redux는 기본적으로 상태관리 툴이다. 버튼을 누르면 1초 뒤에 dispatch 되는 counter를 redux를 통해 만들 필요는 없겠지만 그래도 만들어본다면
redux store를 만들고 dispatch를 하는 과정에서 1초의 딜레이를 주어야 할 것이다.
이 부분을 redux thunk가 해결해줄 것이다.
middleware와의 차이점은 인자로 받는게 무엇인지에
따라 다른 행동을 해주는 middleware라는 점이다.
// normal
const middleware=(store)=>(next)=>(action)=>{
// 원하는 코드를 입력
next(action); // 실제 dispatch가 발생 ex) dispatch(logIn({...})) , dispatch(logOut({...}))
// 원하는 코드를 입력
}
예를 들어, 아래와 같은 action, dispatch 구조라면 기본적인 redux middleware가 작동하게 된다.
const logIn=(data)=>{
return{
type: 'LOG_IN',
data,
}
}
dispatch(logIn({
id:'admin',
name:'ABC',
}))
```js
// thunk
const thunkMiddleware=(store)=>(next)=>(action)=>{
if(typeof action === 'function'){
return action(store.dispatch, store.getState);
}
}
action이 함수여야 하는데 비동기 처리를 해야만 하는 logIn의 경우를 보자
const logIn = (data) => { // 1. (1)
return (dispatch, getState) => { // 2. (2)
dispatch(logInRequest(data)); // 3. (3)
try { // 4. (4)
setTimeout(() => {
dispatch(
logInSuccess({
id: 'youngJoo',
number: 000,
})
);
console.log('2second');
}, 2000);
} catch (e) {
dispatch(logInFailure(e));
}
};
};
(1) logIn action은 원래대로 dispatch를 통해 들어오는 data를 그대로 받고
return을 함수로 넘겨준다.
(2) return이 함수이므로 thunk middleware를 만나 인자로 store.dispatch, store.getState를 받는다.
(3) dispatch를 받았으므로 action 내부에서 다른 action을 호출할 수 있게 되어 logInRequest를 호출한다.
(4) try, catch 구문을 통해 성공시에는 또 다시 성공 action을 catch에는 실패 action을 걸어준다.
const thunkMiddleware=(store)=>(next)=>(action)=>{
if(typeof action === 'function'){
return action(store.dispatch, store.getState);
}
}
// store.js
const firstMiddleWare = (store) => (dispatch) => (action) => {
dispatch(action);
console.log('after dispatching: ', action);
};
const thunkMiddleware = (store) => (dispatch) => (action) => {
if (typeof action === 'function') {
return action(store.dispatch, store.getState);
}
return dispatch(action);
};
const enhancer = applyMiddleware(firstMiddleWare, thunkMiddleware);
// action.js
const logIn = (data) => {
return (dispatch, getState) => {
dispatch(logInRequest(data));
try {
setTimeout(() => {
dispatch(
logInSuccess({
id: 'youngJoo',
number: 000,
})
);
}, 2000);
} catch (e) {
dispatch(logInFailure(e));
}
};
};
const logInRequest = (data) => {
return {
type: 'LOG_IN_REQUEST',
data,
};
};
const logInSuccess = (data) => {
return {
type: 'LOG_IN_SUCCESS',
data,
};
};
const logInFailure = (error) => {
return {
type: 'LOG_IN_FAILURE',
error,
};
};