RTK + redux-thunk + json-server

Rock Kyun·2023년 11월 30일
1

오늘 배운 것

  • RTK와 json-server 연동
  • 서버 통시의 결과에 따른 redux state 업데이트

redux-thunk

  • 어제 서버와 통신하며 프로젝트를 진행해봤는데
    모든 컴포넌트에서 통신하는 방법 말고 redux 모듈에서
    서버와 통신은 못 하나..
    서버 상태에 따라서 자동으로 state를 어떻게 변경하지..
    이런 의문이 있었는데
    redux-thunk를 배우고 나서야 의문이 풀렸다.

사전지식: middleware

  • redux-thunk에서 미들웨어는
    리듀서로 전달되는 액션이 한 번 거쳐가는 부분인데
    이 미들웨어에서 우리는 통신에 관여를 할 수 있게 되는 것.
    결국에는 reducer로 전해지긴 하는데
    통신의 결과에 따라 reducer로 보낼지 extraReducer로 보낼지 설정하는 것이다.

redux-thunk란

  • 리덕스 환경에서의 비동기 통신을 위한 미들웨어

일반 redux, RTK 작동 방식
1. dispatch(actionCreator()) ------------> reducer
2. reducer --------------> store (action 객체에 따른 state 변경 적용)

redux-thunk 추가 시 작동 방식
1. dispatch(thunk()) ------------> middleware
2. middleware ---------------------------> extraReducer
2. extraReducer --------------> store (action 객체에 따른 state 변경 적용)

middleware 추가

  • 서버와 통신이 필요한 redux의 모듈로 가서
    createAsyncThunk() 메서드로 생성.
    이 메서드는 (이름, 함수)를 인자로 받는다.

  • createAsyncThunk() 메서드의 첫 인자 이름은 자유롭게 (이름은 미들웨어 이름과 맞춰주는 것이 좋겠다)

  • 두 번째 인자인 함수는 비동기 통신이 시작되므로
    async 함수로 작성하자.

  • 이 함수의 인자로는 컴포넌트에서 dispatch를 사용하여
    전달한 payload와 redux-thunk에 내장되어 있는 thunk 객체를 전달.

  • 함수 내에서 비동기 통신을 시작하는데
    이때 thunkAPI를 통해 서버 통신의 결과에 따라
    결과에 해당하는 reducer로 각각의 값을 전달한다.

성공 시 - 요청한 데이터 객체
실패 시 - error 객체

<redux/modules/messages.js>

export const __getMessages = createAsyncThunk(
  "GET_MESSAGES",
  // 서버의 상태에 따라 작동
  async (payload, thunkAPI) => {
    try {
      const res = await axios.get('http://localhost:4000/messages');
      // 네트워크 요청이 성공 시
      return thunkAPI.fulfillWithValue(res.data);
    }
    catch (err) {
      // 네트워크 요청이 실패 시
      return thunkAPI.rejectWithValue(err)
    }
  }
)

미들웨어와 연결되는 extraReducer 생성

  • extraReducer는 기존에 만들어져있는 slice에 생성한다.
  • 위의 middleware에서 통신의 결과에 따라
    해당하는 상태의 값이 가야 할 extraReducer로 값이 자동으로 전달된다

통신결과 (pending) -------> [<미들웨어이름>.pending] reducer
통신결과 (fulfilled) --------> [<미들웨어이름>.fulfilled] reducer
통신결과 (rejected) -------> [<미들웨어이름>.rejected] reducer

  • 현재 extraReducers의 형태는 아래와 같다.
< RTK 2.0 미만의 extraRducers >
  
  createSlice({
  ....
  
  extraReducers: {
  	[<미들웨어이름>.pending]: (state) => {
    	// 스태이트를 변경 할 코드
    },
    [<미들웨어이름>.fulfilled]: (state, payload) => {
    	// 스태이트를 변경 할 코드
    },
    [<미들웨어이름>.rejected]: (state) => {
    	// 스태이트를 변경 할 코드
    },
  }
  
  ....
})
  

아직은 이르지만 알아두면 좋을 것 RTK 2.0

  • 위의 extraReducer는 RTK가 2.0이 되면 이제 사용할 수 없게 된다.
  • RTK가 2.0이 되면 builder를 사용하여 extraReducers를 생성하는데
  • builder를 인자로 받는 함수로 작성하는 것 외에 크게 변동이 있지는 않다
extraReducers: (builder) => {
    builder
      .addCase(__getMessages.pending, (state) => {
        state.isLoading = true;
        state.isError = false;
      })
      .addCase(__getMessages.fulfilled, (state, action) => {
        state.isLoading = false;
        state.isError = false;
        state.messages = action.payload
      })
      .addCase(__getMessages.rejected, (state, action) => {
        state.isLoading = false;
        state.isError = true;
        state.error = action.payload
      },)
  }

느낀점

  • 서버 통신할 때마다 redux를 같이 업데이트 해주다니
    너무 편했고 멋있다.
    이제 서버의 데이터를 업데이트 할 때
    redux 모듈에서 export 해준 미들웨어를 작동시켜주면
    서버에서 업데이트 된 데이터로 redux를 최신의 상태로 갱신할 수 있다.

0개의 댓글