리덕스+리액트 Redux with React #7 덕스패턴

eunji hwang·2020년 7월 14일
0

REDUX + REACT

목록 보기
7/9

덕스패턴(duck's pattern)

  • 연관된 action-types, action-creater, reducer 를 하나의 파일에 작성
  • reducer는 export default 로 내보내기
  • action-creater는 export 로 내보내기
  • action-types는 접두사+액션이름으로 작성(예: todos/CREATE)

리덕스+리액트 immer 사용하기 : immerWraper-createReducer()

// 여기서 사용한 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 : 덕스패턴 중복 코드 분리

덕스패턴을 사용하면서 중복되는 코드를 분리하여 사용하자.

  • CREATE/DELETE/UPDATE 와 같은 공통분모
  • action-type, action-creater, reducer를 리턴
// 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)

mergeReducers.js

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 함수는 리듀서를 반환한다.

참고 : 책 : 실전 리액트 프로그래밍/이재승 저

profile
TIL 기록 블로그 :: 문제가 있는 글엔 댓글 부탁드려요!

0개의 댓글