on
서버에서 가져 온 데이터가 redux store에 저장되는 않는 문제_immer...
서버에서 가져 온 데이터가 redux store에 저장되는 않는 문제_immer...
문제
redux store
API 통신 결과
현재 mainPage redux store에는 크게 콘텐츠를 보여주는 contents와 사용자 방을 보여주는 roomList가 저장되어 있다.
redux-saga를 통해 서버와 API 통신을 하여 각각의 배열 내에 데이터들을 적재해주는 과정에서 문제가 발생하였는데, contents에 해당하는 데이터들은 서버에서 문제 없이 가져와 저장되는 반면에, roomList에 해당하는 데이터들은 저장되지 않았다.
처음에는 서버와 API 통신하는 과정에서 문제가 발생한 줄 알고 Promise 후속 메서드인 then 메서드 내에서 콘솔을 찍어봤는데, 문제 없이 roomList에 해당하는 데이터들도 가져왔다.
문제해결
한참을 해당 Blocker에 대해서 고민한 결과, 리액트 상에서 불변성을 지켜주지 못해 발생한 문제임을 확인하였다.
아래와 같이 코드 상에서 contents와 roomList에 해당하는 API 통신을 진행하였고,
useEffect(() => { dispatch(initializeMainForm()); // mainPage 초기화 if (sort === "friends") { batch(() => { dispatch(friendList()); dispatch(friends()); }); } else { batch(() => { dispatch(content({ sort })) dispatch(rooms({ sort })); }); } resetPageScroll(); }, [dispatch, sort]);
redux-saga를 통해 받아 온 데이터를 action.payload에 할당하고 redux-store에서 contents와 roomList 배열에 해당 데이터를 저장하는 초기 코드는 다음과 같았다.
const mainForm = handleActions( { [INITIALIZE_MAINFORM]: state => initialState, [CONTENT_SUCCESS]: ({ contents }, { payload: { message } }) => ({ contents: contents.concat(message), contentsError: null, }), [CONTENT_FAILURE]: (state, { payload: error }) => ({ ...state, contentsError: error, }), [ROOMS_SUCCESS]: ({ contents }, { payload: { message } }) => ({ contents: contents.concat(message), contentsError: null, }), [ROOMS_FAILURE]: (state, { payload: error }) => ({ ...state, contentsError: error, }), }, initialState );
contents와 roomList를 감싸고 있는 상위 객체_initialState의 이전 값을 복사하여 새로운 값을 할당하지 않은 채, CONTENT_SUCCESS / ROOMS_SUCCESS 이벤트가 발생할 때마다 새로운 객체 값을 재할당해주는 바람에 해당 Blocker가 발생하였던 것이다.
이에 해당 코드의 불변성을 좀 더 안정적이고 편하게 지켜주기 위해 immer 모듈의 produce를 사용하여 리팩토링하여 문제를 해결하였다.
const mainForm = handleActions( { [INITIALIZE_MAINFORM]: state => initialState, [CONTENT_SUCCESS]: (state, { payload: { message } }) => produce(state, draft => { draft.contents = state.contents.concat(message); draft.contentsError = null; }), [CONTENT_FAILURE]: (state, { payload: error }) => ({ ...state, contentsError: error, }), [ROOMS_SUCCESS]: (state, { payload: { message } }) => produce(state, draft => { draft.contents = state.contents.concat(message); draft.contentsError = null; }), [ROOMS_FAILURE]: (state, { payload: error }) => ({ ...state, contentsError: error, }), }, initialState );
결과화면
contents 라는 의미가 다소 불명확한 느낌이 들어 contentList로 키 값을 수정하였다
from http://choi95.tistory.com/187 by ccl(A) rewrite - 2021-12-24 20:27:41