export default
로 내보내기export
로 내보내기// 여기서 사용한 createReducer는 immerWrapper로 만든 함수!
import createReducer from 'src/common/createReducer'
const CREATE = 'todos/CREATE';
const DELETE = 'todos/DELETE';
export const createTodos = (todo) => {
return {
type: CREATE,
payload: todo,
};
};
export const deleteTodos = (id) => {
return {
type: DELETE,
payload: id,
};
};
const initState = { todos: [] };
const reducer = createReducer(initState, {
[CREATE]: (state, action) => {
state.todos.push(todo);
},
[DELETE]: (state, action) => {},
});
export default reducer;
폴더구조
- src
- redux
- duckA.js
- duckB.js
- index.js (store, rootReducer, store-debuging, action-test)
- common : 공통파일
- createReducer.js : immerWrapper
- createItemsLogic.js : 덕스패턴 중복 코드 분리
덕스패턴을 사용하면서 중복되는 코드를 분리하여 사용하자.
// createItemLogic
//! 덕패턴 공통분모 기능 분리
import createReducer from './createReducer';
export default function createItemsLogic(name) {
// add, remove, edit에 관한 types
const ADD = `${name}/ADD`;
const REMOVE = `${name}/REMOVE`;
const EDIT = `${name}/EDIT`;
// add, remove, edit에 관한 action-creater
const add = (item) => ({ type: ADD, item });
const remove = (item) => ({ type: REMOVE, item });
const edit = (item) => ({ type: EDIT, item });
// add, remove, edit에 관한 reducer
const reducer = createReducer(
{
[name]: [], // state초기값
},
{ // handelr
[ADD]: (state, action) => state[name].push(action.item),
[REMOVE]: (state, action) => {
const index = state[name].findIndex(
(item) => item.id === action.item.id
);
state[name].splice(index, 1);
},
[EDIT]: (state, action) => {
const index = state[name].findIndex(
(item) => item.id === action.item.id
);
if (index >= 0) state[name][index] = action.item;
},
}
);
return { add, remove, edit, reducer }; // 반환
}
createItemLogic.js
사용해서 add, remove, edit, reducer 생성// createItemLogic.js 사용해서 timelineDuck을 만들자
import createReducer from '../common/createReducer' // immerWrapper적용된 리듀서 생성
import createItemLogic from '../common/createItemLogic' // 액션타입/생성자/리듀서 생성
import mergeReducers from '../common/mergeReducers' // 반환리듀서+신규리듀서 합치기 기능
// 해당 덕스패턴의 이름을 지정
const DUCK_NAME='timeline'
// 반환값 디스트럭처링
const {add, remove, edit, reducer:timelineReducer} = createItemLogic(DUCK_NAME);
// createItemLogic으로 생성한 값을 대입
export const addTimeline = add;
export const removeTimeline = remove;
export const editTimeline = edit;
// 필요한 types/action-creater/reducer 추가생성
const INCRESE_NEXT_PAGE=`${DUCK_NAME}/INCRESE_NEXT_PAGE`
export const increseNextPage =()=> ({type:INCRESE_NEXT_PAGE})
// 추가할 초기 state만 작성한다
const initState = {nextPage:0}
const reducer = createReducer(initState,{
[INCRESE_NEXT_PAGE] : (state,action) => (state.nextPage+=1)
})
const reducers =[reducer,timelineReducer]
export default mergeReducers(reducers)
createItemLogic
를 통해 로직구현을 할때 반환된 리듀서와, 신규생성된 리듀서를 합처 export default 해주기 위해 mergeReducers
모듈을 만들어보자.
combineReducer()
를 사용할 수도 있지만. 리듀서에 접근할 때 깊이가 깊어지게 되기 때문에 mergeReducers.js
를 생성한다// mergeReducer.js
export default function mergeReducer(reducers) {
// reducers = [returnReducer, newReducer]
// 리듀서 반환
return function (state, action) {
if (!state) {
// 초기 상태값을 계산할때 모든 리듀서 함수의 결과값을 합침
return reducers.reduce((acc, r) => ({ ...acc, ...r(state, action) }), {});
} else {
// 초기화 단계가 아니라면 입력된 모든 리듀서를 호출 -> 다음 상태값 반환
let nextState = state;
for (const r of reducers) {
nextState = r(nextState, action);
}
return nextState;
}
};
}
mergeReducer
함수는 리듀서를 반환한다.