일반 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 변경 적용)
서버와 통신이 필요한 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)
}
}
)
통신결과 (pending) -------> [<미들웨어이름>.pending] reducer
통신결과 (fulfilled) --------> [<미들웨어이름>.fulfilled] reducer
통신결과 (rejected) -------> [<미들웨어이름>.rejected] reducer
< RTK 2.0 미만의 extraRducers >
createSlice({
....
extraReducers: {
[<미들웨어이름>.pending]: (state) => {
// 스태이트를 변경 할 코드
},
[<미들웨어이름>.fulfilled]: (state, payload) => {
// 스태이트를 변경 할 코드
},
[<미들웨어이름>.rejected]: (state) => {
// 스태이트를 변경 할 코드
},
}
....
})
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
},)
}