FrontEnd/Redux

[ReduxToolkit] createAsyncThunk

문스코딩 2023. 8. 14. 14:38

redux에서 비동기함수 처리는 [redux-thunk](https://github.com/reduxjs/redux-thunk)라는 별도의 미들웨어를 통해야 한다.

반면 rtk은 비동기함수 처리를 위해 createAsyncThunk 함수를 내장하고 있다.

 

Thunk란?

https://moonscode.tistory.com/249

 

Redux redux-thunk

Thunk란? 먼저 thunk를 이해해야 redux가 비동기를 어떻게 처리하는지 이해할 수 있다. https://ko.wikipedia.org/wiki/%EC%8D%BD%ED%81%AC [썽크 - 위키백과, 우리 모두의 백과사전 위키백과, 우리 모두의 백과사전.

moonscode.tistory.com

 

createAsyncThunk란?

redux-thunk는 단순히 내 코드블럭을 wrapping하여 실행을 지연시키는 함수이다.

createAsyncThunk는 이 redux-thunk 기능을 구조화한 API이다.

지연단계를 pending, fulfilled, rejected 3단계로 구조화하여 제공하고 다양한 옵션으로 그 과정을 세밀히 조정할 수 있다.

pending thunk 실행중
fulfilled thunk 완료
rejected thunk 실패

일차적으로 반환받는 결과는 thunk의 단계이다.

thunk의 단계가 fulfilled이 되면 비로소 thunk의 결과값을 받을 수 있다.

 

 

 

 

createAsyncThunk 선언.

createAsyncThunk는 createAction을 통해서 pending, fulfilled 그리고 rejected 세 가지 상태를 반환.

(createAsyncThunk에서 반환하는 단계도 redux에서는 action으로 정의)

// fetchUserById.pending
// fetchUserById.fulfilled
// fetchUserById.rejected
const fetchUserById = createAsyncThunk(
  // param1. type - thunk를 식별하기 위한 action type
  // 'users/fetchByIdStatus/pending'
  // 'users/fetchByIdStatus/fulfilled'
  // 'users/fetchByIdStatus/rejected'
  'users/fetchByIdStatus',
  // param2. payloadCreator - (비동기) 로직을 반환하는 함수
  // (arg, thunkAPI) => {}
  // arg - dispatch할 때 전달된 매개변수
  // thunkAPI = { dispatch, getState, extra, requestId, signal, rejectWithValue, fulfillWithValue } - redux에서 thunk 함수로 전달하는 매개변수와 옵션
  async (userId: number, thunkAPI) => {
    const response = await userAPI.fetchById(userId)
    return response.data
  }
  // param3. options
  // { condition, dispatchConditionRejection, idGenerator, serializeError, getPendingMeta }
)


// Then, handle actions in your reducers:
const usersSlice = createSlice({
  name: 'users',
  initialState,
  reducers: {
    // standard reducer logic, with auto-generated action types per reducer
  },
  extraReducers: (builder) => {
    // Add reducers for additional action types here, and handle loading state as needed
    builder.addCase(fetchUserById.fulfilled, (state, action) => {
      // Add user to the state array
      state.entities.push(action.payload)
    })
  },
})

 

createAsyncThunk Result.

createAsyncThunk는 Promise를 반환.

비동기의 결과값(Thunk 선언. 예제에서 response.data 값)에 접근하고 싶다면?

extraReducers에서 fulfilled 단계를 정의하면 되지만, 클릭이벤트와 같이 redux의 context 밖에서 처리하려면 unwrap 속성이 필요

without unwrap unwrap
반환된 Promise를 직접 사용하여 비동기 작업을 처리. 반환된 Promise에서 비동기 작업의 결과값을 추출.
// thunk는 기본적으로 promise(함수의 단계를 반환하는 promise)를 반환
const onClick = () => {
  dispatch(fetchUserById(userId)).then(() => {
    // do additional work
  })
}

// unwrap
// createAsyncThunk가 반환한 Promise에는 fulfilled, rejected 상태를 처리할 수 있는 unwrap 속성을 가진다.
const onClick = () => {
  dispatch(fetchUserById(userId))
    .unwrap()
    .then((originalPromiseResult) => {
      // handle result here
    })
    .catch((rejectedValueOrSerializedError) => {
      // handle error here
    })
}

// unwrapResult
const onClick = () => {
  dispatch(fetchUserById(userId))
    .then(unwrapResult)
    .then((originalPromiseResult) => {
      // handle result here
    })
    .catch((rejectedValueOrSerializedError) => {
      // handle result here
    })
}

 

반응형

'FrontEnd > Redux' 카테고리의 다른 글

[Redux] redux-thunk  (0) 2023.08.14
[Redux] redux-orm  (0) 2023.08.10
[Redux] with RTK  (0) 2023.08.01