redux-action으로 action 관리하기 및 Immer으로 불변성 유지하기

wonkeunC·2022년 4월 30일
1

JavaScript

목록 보기
14/15
post-thumbnail

알고가기
1. Redux는 React에 종속된 라이브러리가 아닌 JavaScript의 state를 관리하기 위한 라이브러리이다.
2. Ducks 구조 : action, action 생성자, reducer이 하나의 파일에 들어가는 것.

Firestore에 임의로 구현한 유저의 프로필 정보, 게시글 내용 등의 데이터를 가져와서 값을 넘겨주는 함수를 구현하는데 이때 reduce함수를 사용하여 좀 더Javascript스럽게 코드를 구현해 보려고 한다.

Firebase (Cloud Firestore) 데이터.


import { createAction, handleActions } from 'redux-actions';
import { produce } from 'immer';
import { firestore } from '../../../shared/Firebase';

const initialState = { // 최종적으로 데이터의 값을 담을 배열 그릇이다.
  list: [],
};

🍕 redux-actions로 action 관리하기

1.createAction을 이용하여 action생성 자동화 하기.

Redux의 action을 구현하다 보면 action 생성자를 하나씩 만들어야 하는 것을 볼 수 있다.

// 일반적인 action 형식
export const setPost = (post_list) => ({
    type: types.SET_POST,
    post_list
});

이는 파라미터로 전달받은 값을 객체에 넣어주는 단순한 패턴이다.
이런 귀찮고 단순 작업을 createAction을 이용해 해결시킬 수 있다.

// createAction 형식
function createAction(type, (parameter) => ({parameter}))
// 적용
export const setPost = createAction(SET_POST, (post_list) => ({post_list}))

2.switch 문 대신 handleActions 사용하기

handleActions를 사용하면 기존 switch로 작성한 방식보다 좀 더 간단히 코드를 작성할 수 있을뿐더러 scope가 reducer 함수로 설정되어 case 문에서 let, const의 변수를 선언하다 같은 이름이 중첩될 시 발생하는 에러를 보안할 수 있다.

//기존의 방식
const reducer = (state={}, action={}) => {
switch(action.type){
  case SET_POST : {
   state.list = action.post_list; 
 
  }   
 }
}

//handleActions 방식
const reducer = handleActions({
[SET_POST] : (state,action) => {
 state.list = action.payload.post_list
// createAction()을 사용해서 기존 방식과 다른 payload를 써줘야한다.
// payload에 우리가 담은 값이 존재하게 된다.
 }
},{}); // initialState = {} 


🍕 Immer & produce()로 Redux 불변성 유지시키기.

🔍 React와 Redux에서 불변성을 유지 시켜줘야하는 이유!

React와 Redux는 setState 또는 dispatch 되었을 때 re-rendering이 일어난다.
불필요한 재렌더링은 웹 성능을 저하시킬 수 있기 때문에 useCallback을 사용하게 되는데
이 메서드는 state와 props의 변화를 감지해 변화가 일어날 경우만 렌더링을 허용한다!
여기서 불변성이 필요한 이유는 setState나 Dispatch를 이용해서 상태를 바꾸지 않는다면 re-rendering이 일어나지 않기 때문이다.

리덕스를 사용하는 이유 중 하나가 히스토리가 관리되기 때문에 redux의 state 값을 변경할 때는 불변성을 유지해 줘야 한다.
변경하기 전 state 값과 변경 후의 state의 값을 비교하기 위함이다.

// Immer 패키지의 produce() 사용하기.
export default handleActions({
[SET_POST] : (state, action) => produce(state, (draft) => {})
  // draft가 있는 부분 : 원본 값을 가지고 어떠한 작업을 하고싶은지.
})

Immer는 A를 받고 복사해서 A1 을 만들게 되고 A대신 A1을 고치라고 한다.
이렇게 나온 A1을 불변성 유지를 신경쓰지 않고

const A = {a: 1, b: 2, c: 3};
A.b = 100;

A1이 아닌 A에 대하여 값을 변경시켜도 Immer는 알아서 값을 바꾼 A가 아닌 복사한 A1을 가르키고 불변성 유지를 시켜준다. (불변성 유지를 알아서 잘 해줌!)



<> getPostFB() 함수 작성 전 살펴보기.

  1. 📚 firestore 데이터 가져오는 방법!
  2. setPost() 란?
const SET_POST = 'SET_POST';
const setPost = createAction(SET_POST, (post_list) => ({ post_list }));

export default handleActions(
  {
    [SET_POST]: (state, action) =>
      produce(state, (draft) => { 
// draft는 state의 값과 동일하며 값에 대한 불변성 유지를 위해 draft를 대신 사용한다.
        draft.list = action.payload.post_list;
// payload는 어떤 타입의 값이든 가질 수 있다. 이는 action이 가지는 payload를 의미한다. 
// type또는 status를 제외한 action의 정보는 모두 payload에 있어야 한다.
      }),
  },
  initialState
);

📝 getPostFB() 함수 작성하기

defaultProps에 수기로 작성한 데이터 대신 firestore에 작성한 데이터들을 reducer의 SET_POST 함수를 통해 최종적으로 list 배열에 firestore 데이터를 넣어주는 함수이다.

const getPostFB = () => {
  return function(dispatch, getState, { history }) {
    const postDB = firestore.collection('post'); 📚

    postDB.get().then((docs) => { 
// 📚 postDB.get() 데이터를 가져옴 then() 가져온 데이터를 후처리 사용.
      let post_list = [];
      docs.forEach((docElements) => {
// Post.defaultProps = {..}의 키 값에 임의로 작성한 데이터를 firestore 데이터 값으로 적용하기
        let _post = { 
          id: docElements.id,
          ...docElements.data(),
        };
        let post = {
          id: _post.id,
          user_info: {
            user_name: _post.user_name,
            user_profile: _post.user_profile,
            user_id: _post.user_id,
          },
          image_url: _post.image_url,
          contents: _post.contents,
          comment_cnt: _post.comment_cnt,
          insert_dt: _post.insert_dt,
        };
        post_list.push(post);
      });
      dispatch(setPost(post_list));
    });
  };
};

profile
개발자로 일어서는 일기

0개의 댓글