[TIL] Redux 2. Never do mutate the state.

2022. 10. 13. 15:17React/Redux

이 시리즈는 노마드 코더님의 "초보자를 위한 리덕스 101"을 보고 배운 내용을 정리합니다.

비약이나 틀린 내용이 있다면 언제든 댓글로 알려주세요..! (매우 환영입니다😀)

 

[시작하기 전에]

이번 2편은 React가 아니라 순수 JavaScript 환경에서 실습을 해봅니다.

이후에 React-Redux도 다루니 다른 편을 참고해주세요!


🎛️ TO-DO Apps with Redux

결과물

 

저번 클래스에서 간단한 redux의 사용법을 알아봤다.

1. store를 안에서 primitive type의 state를 관리해보고,
2. state를 관리하는 다양한 기능의 함수를 정의한 다음,
3. action을 넣은뒤 dispatch로 실행하고 subscribe를 리스너로 써 볼 수 있었다.

 

이번엔 primitive type이 아닌 array를 다뤄보면서 mutate에 대한 이야기를 해보려고 한다.

 

 

1. Mutate에 대해서

swr에서도 mutate가 있었는데,

이때 mutate는 서버로부터 최신 데이터를 가져와서 갱신한다. 는 기능을 했다.

상태 관리에서 말하는 mutate라는 단어는 원래 참조하던 object에 새로운 el을 수정한다. 라는 의미이다.

 

const obj = { id: 1, name: russel };

const mutate = (key, val) => {
  obj[key] = val;
}

mutate(age, 25);

 

이런 식의 조작은 mutate 조작이다.

array에서 push, pop, shift, unshift 같은 조작도 역시 mutate 조작이다.

(JavaScript에서 array는 사실 object이기 때문에!)

 

⛔Never do mutate in redux.

 

공식문서에서 mutate로 조작하는 걸 절대 하지 말라고 한다. UI 구조에 문제가 생길 수 있다고 한다.

그러니 꼭 spread 연산자를 쓰거나 filter 함수같은 걸 써서 state를 새로 만들어줘야한다.

 

약간의 뇌피셜을 더하자면, listener로 쓰이는 subscribe 함수가 아마 state가 참조되는 주소를 가져오는게 아닐까 싶다.

그러면 새로 만들어진 state가 들어가면 새 주소로 갱신되니 subscribe 함수가 실행되고, 

mutate로 조작되면 원래 주소랑 같으니 실행이 되지 않을 거다.

 

Writing Reducers with Immer | Redux Toolkit

 

redux-toolkit.js.org

 

2. TODO 리스트 관리를 위해 필요한 state는?

store를 하나만 만들어서 TODO 리스트를 만들 수 있다.

각 리스트의 text 정보를 담은 값 하나, 그리고 timestamp로 고유한 id를 만들어 주면 된다.

 

index.js

const reducer = (state = [], action) => {
    switch (action.type) {
        case ADD_TODO:
            return [...state, { text: action.text, id: Date.now() }];
        case DELETE_TODO:
            return state.filter(v => v.id !== Number(action.id));
        default:
            return state;
    }
};

 

return 할 때,

기존 object에서 뭔가 변화가 생겼다면 spread 연산자를 쓰거나 filter 함수를 써서 새로운 object로 만들어주자.

값을 넘기는 건 action에 줄줄이 늘여서 써주면 된다.

 

const addToDo = (text) => {
    store.dispatch({ type: ADD_TODO, text: text });
}

const deleteToDo = (e) => {
    const id = Number(e.target.parentNode.id);
    store.dispatch({ type: DELETE_TODO, id });
}

 

결과물: (좌) addToDo | (우) deleteToDo

 

 

문득 보다가 TypeScript에서 action에 저렇게 줄줄이 넣어주면 컴파일러가 또 못 알아듣지 않을까 하고 그냥 검색하려다가

그냥 세 번째에 있는거 보고 역시라는 생각이 들었다.

 

 

찾아보니 reducer에서 action type을 미리 넣어주는게 가능했다.

어찌보면 이 친구도 결국엔 함수니 당연할지도?

 

//출처: https://react.vlpt.us/using-typescript/05-ts-redux.html
// 모든 액션 객체들에 대한 타입 준비
type TodosAction =
  | ReturnType<typeof addTodo>
  | ReturnType<typeof toggleTodo>
  | ReturnType<typeof removeTodo>;

// 상태에서 사용 할 할 일 항목 데이터 타입 정의
export type Todo = {
  id: number;
  text: string;
  done: boolean;
};

// 리듀서 작성
function todos(state: TodosState = initialState, action: TodosAction): TodosState {
  //....
}

 

다음에는 드디어 React에서 Redux를 써볼 수 있을 것 같다.

지금 프로젝트에서 redux를 도입해서 코드 개선해보는 과정을 한 번 다뤄봐야할 것 같다.