리덕스 미들웨어란 뭘까?
👩🎓 미들웨어는 액션을 디스패치 했을 때 부터 리듀서로 올때까지의 중간 허브같은 역할을 한다.
미들웨어 구조원리
미들웨어의 기본문법
const origin = store => next => action => {
//미들웨어는 관습적으로 고차원함수로 파라미터를 3개씀.
const result = next(action) or dispatch(action);
//미들웨어에서 할 게 없다고 판단 다음으로 액션을 넘기는 상황
return result;
};
export default origin;
------------------------------------------------------------------------------
// 쉽게 풀이하면 콜백 콜백 콜백 함수다
function middleware(store) {
return function (next) {
return function (action) {
// 하고 싶은 작업...
};
};
};
미들웨어 적용방법
미들웨어를 사용하기 위해서는 스토어에 applyMiddleware라는 기능을 사용.
const store = createStore(rootReducer, applyMiddleware(미들웨어함수명));
//이렇게 넣어줌
만약 미들웨어가 한개를 초과 할 경우 applyMiddleware(미들웨어함수명) 대신
const enhancer = applayMiddleware (
firstMiddleware,
secondMiddleware
)
미들웨어는 원래 동기적
<button onclick={()=>{dispatch(increase())}}>up</button>
클릭 하면 ↓
export const increase = () => ({ type : INCREASE }) 가 실행됨.
실행 되면서, store에 middleware가 있는 지 찾음 = myLogger 이라는 middleware를 발견
const store = createStore(rootReducer, applyMiddleware(myLogger));
-----------------------------------------------------------------
myLogger.js (middleware)
const myLogger = store => next => action => {
// 여기서 해볼 수 있는게
console.log(action)
→ 해석(결과) :
{ type : INCREASE } // object 타입
--------------------------------------------------------------
console.log(store.getState())
→ 해석(결과) :
store = getState = initialState
--------------------------------------------------------------
// 마지막 처리 (next) ↓
const result = next(action) //action을 다음 middleware로 넘김
return result
}
// 근데 여기서 action이 object가 아니라 function 일 경우 비동기 함수 처리하는데 이걸 thunk라 함
미들웨어의 비동기 처리 (실전사례)
기본 셋팅
const GET_USERS_START = 'GET_USERS_START';
const GET_USERS_SUCCESS = 'GET_USERS_SUCCESS';
const GET_USERS_FAIL = 'GET_USERS_FAIL';
export function getUsersStart() {
return {
type: GET_USERS_START,
};
}
export function getUsersSuccess(data) {
return {
type: GET_USERS_SUCCESS,
data,
};
}
export function getUsersFail(error) {
return {
type: GET_USERS_FAIL,
error,
};
}
thunk 함수
function getUsersThunk() {
return async (dispatch, getState) => {
try {
dispatch(getUsersStart());
const res = await axios.get('https://api.github.com/users');
dispatch(getUsersSuccess(res.data));
} catch (e) {
dispatch(getUsersFail());
}
};
}
const thunk = getUsersThunk();
thunk.withExtraArgument = getUsersThunk;
export default thunk;
store
import thunk from 'redux-thunk';
const store = createStore(
reducer,
composeWithDevTools(
applyMiddleware(thunk),
),
);
App.js
export default function App() {
useEffect(() => {
getUsers();
}, []);
}
↓
const getUsers = useCallback(() => {
// 함수가 재 실행 되지 않게 useCallback 사용
dispatch(getUsersThunk()); // 비동기 처리 thunk dispatch로 호출
}, [dispatch]);