애드블럭 종료 후 보실 수 있습니다.

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Redux Toolkit Dependency cycle Error
    Tip 2021. 12. 16. 19:09
    728x90
    반응형

    Redux Saga에서 Redux Toolkit(이하 RTK)으로 바꾸며 큰 만족을 했지만 cycle에러를 피하기 어렵다는 단점이 있다.

    이런 것은 Duck's Pattern의 고질적인 문제이기도 한데, 내가 이 문제를 해결한 방법을 공유하려고 한다.

     

    이 문제가 발생하는 경우에 대해 먼저 설명하자면.

    // aReducer
    
    ...
    
    const aSlice = createSlice({
      name: 'aSlice',
      initialState,
      reducers: {
      	testReducer(state, action){
          // func contents
        }
      },
      extraReducers: (builder) =>
        builder
        .addCase()
        ...
    })
    
    export { testReducer } = aSlice.actions;
    
    export default aSlice.reducer;
    
    // bReducer
    
    ...
    
    const bSlice = createSlice({
      name: 'bSlice',
      initialState,
      reducers: {
      	test2Reducer(state, action){
          // func contents
      },
      extraReducers: (builder) =>
        builder
        .addCase()
        ...
    })
    
    export { test2Reducer } = bSlice.actions;
    
    export default bSlice.reducer;

    주로 RTK를 사용하면 많이 생성하는 구조이다.

    saga를 사용할 때에 비하면 코드 양도 무척 적고 편리하지만 문제가 발생하는 상황은 이런 상황이다.

    // aThunk
    
    import { test2Reducer } from './bReducer';
    
    export const testThunk = createAsyncThunk('a/test', async (test, thunkAPI) => {
    	...
        thunkAPI.dispatch(test2Reducer());
        ...
    })
    
    // bThunk
    
    import { testReducer } from './aReducer';
    
    export const test2Thunk = createAsyncThunk('b/test2', async (test, thunkAPI) => {
    	...
        thunkAPI.dispatch(testReducer());
        ...
    })

    위의 상황은 생각보다 많이 생기는 일이다.

    간략하게 예를 들자면 post reducer에서 comment를 불러와 set 해주고 comment를 추가했을 때 post reducer의 comments 카운트를 변경해주는 상황 같이.

     

    이런 cycle에러의 경우 가장 간단한 방법은 공통으로 사용하거나 하는 데이터들을 다른 폴더 안에서 관리하는 방법인데, 그렇게 되면 프로젝트가 커질 경우 state 묶음은 물론 action까지 모두 파일을 나눠 관리하면 가독성이나 유지보수에 너무 좋지 않다고 생각했다.

     

    그래서 생각한 방법은 아래와 같다.

    // aThunk
    
    export const test2Reducer = createAsyncThunk('b/test2', () => true);
    
    export const testThunk = createAsyncThunk('a/test', async (test, thunkAPI) => {
    	...
        thunkAPI.dispatch(test2Reducer());
        ...
    })
    
    // bThunk
    
    export const testReducer = createAsyncThunk('a/test', () => true);
    
    export const test2Thunk = createAsyncThunk('b/test2', async (test, thunkAPI) => {
    	...
        thunkAPI.dispatch(testReducer());
        ...
    })
    // aReducer
    
    import { testReducer } from 'bThunk';
    ...
    
    const aSlice = createSlice({
      name: 'aSlice',
      initialState,
      reducers: {}
      },
      extraReducers: (builder) =>
        builder
        .addCase(testReducer.fulfilled, (state, action)=>{
        	...testReducer contents
        })
        ...
    })
    
    export default aSlice.reducer;
    
    // bReducer
    
    import { test2Reducer } from 'aThunk';
    ...
    
    const bSlice = createSlice({
      name: 'bSlice',
      initialState,
      reducers: {},
      extraReducers: (builder) =>
        builder
        .addCase(test2Reducer.fulfilled, (state, action)=>{
        	...test2Reducer contents
        })
        ...
    })
    
    export default bSlice.reducer;

     

    위 내용을 간략하게 정리하자면 reducers에 있던 action을 사용하는 Thunk에서 생성한 뒤 import를 해서 사용하면 간단하게 해결된다.

    위와 같은 방법으로도 에러가 발생한다면 그때 업데이트를 진행하도록 하겠다.

    반응형

    댓글

Designed by Tistory.