성장, 그리고 노력

부족하더라도 어제보다 더 잘해지자. 노력은 절대 배신하지 않는다.

상태관리

[Redux & Reducer] 기초 개념 2

제이콥(JACOB) 2019. 12. 10. 01:23

스토어

→ 애플리케이션의 상태(state)를 가지고 있는 곳

createStore라는 함수를 가지고 있고 이를 통해 스토어를 생성

→ 스토어는 애플리케이션 내부에서 유일성을 가진다.

 

플럭스 표준 액션(Flux Standard Action)

→ 액션의 형식을 표준화한 것(with 페이스북 개발자)

→ 디자인 목표: Human-friendly, Useful, Simple

 

액션크리에이터(ActionCreator)

→ 액션을 생성하기 위한 함수

→ 액션크리에이터를 만들어 두면 액션 테스트를 쉽게 할 수 있으며, 실제로 액션을 사용하는 경우에도 직감적으로 쉽게 사용할 수 있다.

const addTask = task => ({
    type: 'ADD_TASK',
    payload: {
        task
    }
})

 

createStore(reducer, [preloadedState], [enhancer])

→ 이름 그대로 스토어 생성때 사용

→ 첫번째 매겨변수에는 리듀서를 전달

→ 4개의 메서드가 들어있음(dispatch, subscribe, getState, replaceReducer)

 

dispatch

→ 액션을 발행함 

→ ADD_Task라는 Type을 가진 액션이 발행되어 리듀서에 의해 상태가 변함

store.dispatch(addTask('따릉이로 한강까지');

 

getState

→ 스토어의 현재 상태를 확인할 수 있음

console.log(store.getState());
//{
//	tasks: ['따릉이로 한강까지']
//}

 

subscribe

→ 스토어의 상태가 변경될 때 호출할 콜백함수를 지정할 수 있음

import { createStore } from 'redux';

const initialState = {
    tasks : []
};

function tasksReducer(state=initialState, action) {
    switch(action.type) {
        case 'ADD_TASK':
            return {
                ...state,
                tasks: state.tasks.concat([action.payload.task])
            };
        default:
            return state;
    }
}

const store = createStore(tasksReducer);

function handleChange() {
    console.log(store.getState());
}

const unsubscribe = store.subscribe(handleChange);

const addTask = task => ({
    type: 'ADD_TASK',
    payload: {
        task
    }
});

store.dispatch(addTask('따릉이로 한강까지'));

→ cf) react-redux에서는 subscribe 관련 기능을 알아서 처리해준다.

 

 

replaceReducer

→ createStore로 스토어를 생성할 때 연결되는 리듀서는 하나!

→ 하지만, 애플리케이션의 규모가 커질수록 리듀서를 분할하고 싶은 경우가 발생하며, 여러 개로 분할한 리듀서를 하나로 묶어 스토어에 연결할 수 있게 conbineReducers라는 메서드를 많이 사용한다.

→ 그런데 분할한 리듀서를 동적으로 읽어 들이고 싶은 경우 스토어에 연결된 리듀서를 이후 다른 리듀서로 변경해야한다. 이때 사용되는 replaceReducer!

→ 특별한 이슈가 없다면 combineReducer를 사용해 리듀서를 하나씩 연결해서 사용하며, 리듀서를 동적으로 로드하고 싶은 경우는 replaceReducer를 사용한다.

 

ex) "태스크를 추가하는 리듀서'와 '태스크를 리셋하는 리듀서'로 분할

import { createStore, replaceReducer } from "redux";

const initialState = {
  tasks: []
};

function addReducer(state = initialState, action) {
  switch (action.type) {
    case "ADD_TASK":
      return {
        ...state,
        tasks: state.tasks.concat([action.payload.task])
      };
    default:
      return state;
  }
}

function resetReducer(state = initialState, action) {
  switch (action.type) {
    case "RESET_TASK":
      return {
        ...state,
        tasks: []
      };
    default:
      return state;
  }
}

const store = createStore(addReducer);

function handleChange() {
  console.log(store.getState());
}

const unsubscribe = store.subscribe(handleChange);

const addTask = task => ({
  type: "ADD_TASK",
  payload: {
    task
  }
});

store.dispatch(addTask("따릉이로 한강까지"));
// -------------------------------------------
store.replaceReducer(resetReducer);

const resetTask = () => ({
  type: "RESET_TASK"
});

store.dispatch(resetTask());

→ resetReducer로 변경한다고 스토어의 상태가 변환하는 것은 아니므로 이전 태스크가 남아 있는다.

 

→ 스토어에 연결돼 있는 리듀서의 변경사항만 적용

 

combineReducer

→ 리덕스가 제공하는 메서드로 각 리듀서를 하나로 모아주는 역할

→ 애플리케이션의 규모가 커지면 하나의 리듀서로 모든 것을 처리하는 것이 굉장히 복잡하고 어렵다, 특히 여러개의 엔티티를 사용하는 애플리케이션의 경우 이러한 분할은 거의 필수라고 할 수 있다.

 

 

참고 URL

https://redux.js.org/faq/code-structure

https://d2.naver.com/helloworld/1848131

반응형

'상태관리' 카테고리의 다른 글

처음 접해보는 MobX - 1편  (0) 2020.02.13
Redux Reducer와 Array.reduce  (0) 2019.12.26
[Redux & Reducer] 기초 개념 1  (0) 2019.12.10