Skip to content

Knowledge: In Home

kimyoungyin edited this page Feb 19, 2022 · 1 revision

에러

1. A non-serializable value was detected in an action, in the path:...

발생상황: event.currentTarget.getBoundingRect() 객체가 return하는 DOMRect를 action에 담아 dispatch하는 코드에서 에러가 발생했다.

이유: 엄청 큰 data를 하나의 action에 담아 dispatch할 경우 발생한는 에러

보통 api에서 받아온 data를 가공하지 않고 바로 action에 담는 경우(thunk나 일반 action이나 마찬가지)

해결: 큰 data를 잘게 쪼개서 action에 담아 dispatch하자. redux-toolkit이 제공하는 prepare를 사용하여 data를 가공한 뒤 dispatch하는 경우도 있다.

큰 data 를 action 에 담지 않아도 발생하는 경우 store 에 아래 코드 추가해주기.

middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      serializableCheck: false,
    }),

2. ReferenceError: Cannot access 'getHomeArticles' before initialization

발생상황: accessToken이 필요한 thunk가 refreshToken 재발급 관련 에러로 인해rejected 되었을 때 authSlice에 연결하여(extraReducer) isLogin을 false를 만들고자 했는데, 해당 thunk명.rejected를 추가하자 마자 위와 같은 에러 발생

이유: createSlice가 return하는 slice를 초기화할 때, 해당 slice 내부에 thunk가 아직 읽히지 않았을 경우에 발생(ducks 패턴 구조의 단점?)

스크린샷 2022-02-08 오후 4 49 41

authSlice가 먼저, homThunk가 나중에 불러와지는데, authSlice에서 먼저 homThunk에서 가져온 thunk를 포함하여 slice를 초기화하려하여 발생하는 것으로 추정

해결: 굳이 extraReducer를 추가하기보단, 해당 thunk에서 ThunkOptions.dispatch()를 이용하여 받는 error 메세지가 refreshToken 재발급 관련 에러라면 authAction.logout() 액션을 dispatch하도록 변경

스크린샷 2022-02-08 오후 4 38 14

Knowledge

1. createAsyncThunk를 통한 비동기 작업 시 extraReduceraction 객체 내부에 원하는 데이터 찾기

아래 객체 전체가 action을 의미하는 것은 아니며, 일반적으로 필요한 data를 찾기 위해 필요한 값만 정리해보았습니다.

참고 자료: redux-toolkit: createAsyncThunk

// action
const action = {
  payload // createAsyncThunk 내부 비동기 함수가 fulfilled되었을 때 return하는 값. pending일 떄 undefined, rejected일 떄 unknown
  meta: {
    arg //  createAsyncThunk를 호출할 때 가져오는 객체
    requestId // 해당 dispatch를 다른 것과 식별하는 고유한 id
    requestStatus // "pending" | "fulfilled" | "rejected"   
  }
}

사용 예시

팔로우/언팔로우 요청을 위해 thunk 호출 시 parameter로 넣어줬던 Username을 pending 상태의 extraReducer에서 조회 후 로딩처리

// 컴포넌트에서 팔로우/언팔로우 thunk dispatch
await dispatch(postFollow({ token, username }))

// pending 상태의 extraReducer에서 username 조회하여 해당 컴포넌트 로딩 처리
.addCase(postUnfollow.pending, (state, action) => {
  state.articles.forEach((article) => {
    if (article.memberUsername === action.meta.arg.username) {
      article.followLoading = true;
    }
  });
})

Clone this wiki locally