[Redux] Reducer

Dodam·2024년 1월 28일
0

[Redux]

목록 보기
5/11
post-thumbnail

Reducer

  • Action이 발생하면, Action을 실제로 처리하는 역할을 하는 함수
    (Action은 State에 변화를 주기 위한 행동이다. 따라서, Reducer는 State에 변화를 주는 역할을 한다.)

  • Reducer는 현재 state를 기반으로 새로운 state를 만들어서 리턴한다.

// Reducer는 현재 State와 Action을 파라미터로 받아서 새로운 State를 만들어 리턴한다.
(state, action) => newState

예) 배열에 아이템을 넣고 빼기 위한 Action을 처리하는 Reducer 함수

function addReducer(state = initialState, action) {
	switch (action.type) {
		case 'PUSH_ITEM':
			return [...state, action.item];
		case 'POP_ITEM':
			const newState = [...state];
			newState.pop();
			return newState;
		default:
			return state;
	}
}

  • 코드 설명

Reducer 함수는 파라미터로 stateaction을 받는다. 이후 action 객체에 필수로 포함되어 있는 type 값에 따라서, 상태에 정해진 변화를 준 뒤에 새로운 상태를 생성해서 리턴한다.

예를 들어, PUSH_ITEM Action의 경우, 배열의 가장 마지막에 새로운 아이템을 추가하여 리턴하고,
POP_ITEM Action의 경우, 배열의 가장 마지막에서 아이템을 하나 제거하고 리턴한다.

여기서 중요한 점은 파라미터로 받은 state가 아닌, 항상 새로운 state를 생성해서 리턴한다는 것이다.

Reducer의 규칙

새로운 state는 파라미터로 받은 ‘현재 state’와 ‘action‘ 객체를 기반으로 생성해야 한다.

외부의 다른 값을 참조하지 않고, 현재 state와 action객체에 들어있는 값만으로 새로운 state를 만들어야 한다.

현재 state를 조작할 수 없으며, 새로운 state를 만들어 `immutable(불변의) update`를 해야 한다.

Reducer가 순수 함수가 되려면 입력값(현재 state)을 조작하면 안되고, 새로운 state를 생성해야 한다.

비동기 로직이나 side effects는 허용되지 않는다.

예를 들어, Reducer 내에서 서버와 통신을 해서 데이터를 받아오거나 하는 등의 동작을 하면 안 된다.

  • side effects란?
    Reducer 외부에서 보여질 수 있는 상태의 변경 또는 동작을 의미한다.
    즉, 순수 함수에서 리턴 값과 직접적으로 관련이 없는 모든 동작이 side effect에 해당한다.
    ex) 콘솔에 로그를 출력, 파일 저장 등

Immutable Update (불변적 업데이트)

현재 State를 변경하지 않고, 새로운 State를 만들어 업데이트 하는 방식

  • 잘못된 업데이트 ❌

현재 state에 있는 value값에 action 객체에 있는 새로운 value 값을 대입

function sampleReducer(state, action) {
	switch (action.type) {
    	case "SAMPLE_ACTION":
    		state.value = action.value;  // 기존 state를 직접 변경
    		return state;
    	default:
    		return state;
    }
}

  • 정상적인 업데이트 ✅

Spread 문법을 사용해 기존 state 객체의 데이터를 복사한 후, value키에 action 객체에 있는 새로운 value값을 넣어준다.

결과적으로 새로운 value 값이 들어간 객체가 새로 만들어진다.

function sampleReducer(state, action) {
	switch (action.type) {
		case "SAMPLE_ACTION":
			return {
				...state,  // 기존 state를 복사 후, 새로운 state를 넣어준다.
				value: action.value
			};
		default:
			return state;
	}
}

복잡한 state 객체를 업데이트 하는 경우

Redux Toolkit을 사용하면 복잡한 객체에 대해서도 손쉽게 불변적 업데이트를 할 수 있다. (내부적으로 immer라는 라이브러리를 사용하기 때문)

// 복잡한 state 객체를 업데이트할 때, Redux Toolkit을 사용하면 쉽게 불변적 업데이트를 할 수 있다.

function sampleReducer(state, action) {
    switch (action.type) {
        case "SAMPLE_ACTION":
            return {
                ...state,
                depth1: {
                    ...state.depth1,
                    depth2: {
                        ...state.depth1.depth2,
                        depth3: {
                            ...state.depth1.depth2.depth3,
                            value: action.value
                        }
                    }
                }
            };
        default:
            return state;
    }
}

CombinedReducers()

리덕스를 사용하다보면 수많은 Action과 Reducer들이 생기게 된다.
이러한 Action과 Reducer는 공통된 카테고리로 모아서 분류할 수 있게 된다.

그런데 리덕스의 CreateStore() 함수에는 첫 번째 파라미터로 reducer 를 하나만 넣을 수 있기 때문에 모든 Action들을 처리하기 위해서는 나눠져 있는 reducer들을 하나로 합쳐야 한다.

이때 사용하는 함수가 바로 combineReducers() 이다.
combineReducer()여러 개의 Reducer들을 하나로 합치는 역할을 한다.

이렇게 모든 Reducer들이 하나로 합쳐진 것을 rootReducer 라고 부르며, createStore() 함수의 첫 번째 파라미터로, 바로 이 rootReducer 가 들어가게 된다.



  • combineReducers() 함수를 사용하는 예시 코드
import { combineReducers } from 'redux';

import postReducer from './reducers/postReducer';
import commentReducer from './reducers/commentReducer';

// postReducer와 commentReducer를 합쳐서 하나의 rootReducer로 만든다.
const rootReducer = combineReducers({
	post: postReducer,
	comment: commentReducer,
});

export default rootReducer;

요약

Reducer

  • Action이 발생하면, Action을 실제로 처리하는 역할을 하는 함수
  • 리덕스 State에 변화를 주는 역할
  • 현재 State와 Action을 파라미터로 받아서 새로운 State를 만들어 리턴
(state, action) => newState

Reducer의 규칙들

  • 새로운 State는 오직 현재 State와 Action 객체만을 가지고 만들어야 한다.
  • 현재 State를 수정하는 것은 허용되지 않으며, 불변적 업데이트(immutable updates)를 해야 한다.
  • 비동기 로직이나 다른 Side Effects는 허용되지 않는다.
    예) 서버와 통신해서 데이터를 받아오거나, 콘솔에 로그를 출력하거나, 파일을 저장하는 것 등

불변적 업데이트(Immutable updates)

  • 현재 State를 변경하지 않고, 새로운 State를 만들어 업데이트하는 방식
  • JavaScript의 Spread 문법을 주로 사용한다.
  • Redux Toolkit을 사용하면 손쉽게 Immutable Update를 할 수 있다.

combineReducers()

  • 여러 개의 Reducer들을 하나로 합치는 역할을 하는 함수
  • 모든 Reducer들이 하나로 합쳐진 것을 rootReducer라고 부른다.
profile
Good things take time

0개의 댓글