미들웨어는 action을 검사하는 검문소 역활을 하게된다.
리덕스에서는 데이터가 단방향으로 흐르게 되는데, 데이터를 검사할때에
action -> [ ] -> store에서 검사를 하면된다.
즉 미들웨어는 리듀서 실행 전후에 위치하게된다.
리덕스는 스토어에 미들웨어를 등록할수있도록 applyMiddleware()함수를 제공한다.
또한 미들웨어를 사용하여서 action을 다르게 변경시켜서 사용할수도있다.
const customMiddleware = store => nextRunner => action => {
console.log('미들웨어에 전달된 액션 객체', action);
console.log('리듀서 실행이전', store.getState());
//nextRunner로 리듀서 실행 이전과 이후를 나눌수있다.
const result = nextRunner(action);
console.log('리듀서 실행이후', store.getState());
return result;
};
//미들웨어로 액션 변형
const customMiddleware1 = () => nextRunner => action => {
if (action.type === SET_TRANSACTION_LIST) {
return nextRunner({
...action,
payload: [
{
id: 0,
code: 'DOIT',
name: '두잇코인(DOIT)',
totalPrice: 1000000000,
currentPrice: 25000,
datetime: '현재시간',
},
],
});
}
return nextRunner(action);
};
export default initStates =>
createStore(
combineReducers(reducers),
initStates,
composeWithDevTools(
applyMiddleware(customMiddleware, customMiddleware1)
)
)
비동기 지연 작업을 처리하려면 콜백함수를 사용하여야 한다.
즉 Action을 사용한 비동기 처리를 할때에는 객체 형태의 액션을
함수 형태의 액션으로 구성(액션 함수안에 dispatch 함수 호출)을 해야한다.
이때에 손쉽게 액션이 객체가 아니라 함수형태로 만들어서 사용하는 것이
redux-thunk
미들웨어 이다.
원래 액션은 type, payload로 구성된 객체 이지만
redux-thunk를 사용하면 dispatch()함수와 스토어 데이터를 액션에 포함시킬수있다.
ex)
function thunkAction(somePayload){
return function(dispatch, getState){
dispatch({
type: 'SOME_ACTION_TYPE',
payload: somePayload,
})
dispatch({
type: 'SOME_EXTRA_ACTION_TYPE',
payload: {
...getState().resoure,
somepayload,
}
})
}
}
yarn add redux-thunk
redux-thunk의 리듀서는 switch문을 사용해 액션에 맞는 작업을 추가한다.
총 4가지의 상황에 대비해야한다.
export function thunkReducer(state, action){
const {type, payload} = action;
switch(type){
case 'START':{
return {...state, loading: true};
}
case 'SUCCESS': {
return {...state, payload};
}
case 'FAILURE' : {
return {...state, error: true};
}
case 'FINISH' : {
return {...state, loading: false};
}
default:
return state;
}
}
redux-pack은 redux-thunk와 비슷하게 비동기 처리를 해주는 미들웨어 방식이지만,
조금더 간단하고 효율적인 방법으로 제어를 할수있다.
import { handle } from 'redux-pack';
export function packReducer(state, action) {
const { type, payload } = action;
if (action === 'REDUX_PACK') {
return handle(state, action, {
start: prevState => ({
...prevState, loading: true
}),
success: prevState => ({ ...state, payload }),
failure: prevState => ({ ...state, error: true, }),
finish: prevState => ({
...state, loading: false,
})
});
}
return state;
}
yarn add redux-pack
변환 작업 성능을 향상시킬때에 사용한다.
- reselect 설치
yarn add reselect
import { createSelector } from 'reselect';
const getX = state => state.x
const getY = state => state.y
const getXPlusY = createSelector([getX, getY], (x, y) => x + y);
getXPlusY({x: 3, y: 10}); // 앞으로 13을 반환할예정
getXPlusY({x: 4, y: 6}); // 앞으로 10을 반환할 예정