일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- @media
- 그럼에도불구하고
- JavaScript
- node.js
- 변수
- media query
- cleancode
- Servlet
- max-width
- java
- github
- 그럼에도 불구하고
- frontend
- JS
- node
- git
- 자바문제풀이
- 프론트엔드
- react
- 반응형 페이지
- webpack
- TypeScript
- redux
- react-router-dom
- HTML
- 자바
- CSS
- coding
- 코딩테스트
- 코드업
- Today
- Total
그럼에도 불구하고
[Redux] createAsyncThunk란? 본문
createAsyncThunk에 대해 알아보겠습니다.
🧑🏻💻 createAsyncThunk
프로그램을 개발하다 보면, 전역에서 자주 사용되는 api를 호출하거나, api 호출한 결과를 여러 군데에서 사용해야 할 상황이 생기는데, 이와 같은 비동기 처리를 redux store에서는 자체적으로 하지 못하는 단점이 있습니다.
따라서 Redux를 사용할 때는 redux-thunk, redux-saga와 같은 미들웨어를 사용해서 비동기 처리를 진행했습니다.
하지만, 위의 기능들 같은 경우 Redux와 같이 사용하기 위한 러닝커브가 조금 있기 때문에, Redux Toolkit의 createAsyncThunk를 사용해 비동기 처리를 진행하고는 합니다.
📌 사용법
createAsyncThunk
1. createAsyncThunk는 함수이며 async 함수를 수행합니다.
2. createAsyncThunk 함수는 두 가지 인자를 받습니다.
createAsyncThunk(actionType, callbackFunction)
1 2 3 4 5 6 | export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => { const response = await client.get('/fakeApi/posts'); return response.data }); | cs |
action Type String은 slice의 이름을 말합니다. 여기서는 async 함수를 실행시키고 promise 결과를 반환합니다.
반환하는 곳은 reducer의 slice 함수에 반환하게 됩니다.
⭐️ extraReducer
위에서 비동기 처리를 할 액션을 정의했으니 리듀서에 연결하면 되겠죠?
다만, 앞에서 설명했듯이 Redux에서는 자체적으로 비동기 처리를 지원하지 않기 때문에, extraReducer라는 것을 사용해 createAsyncThunk로 생성한 Thunk를 등록시켜야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | const postsSlice = createSlice({ name: "posts", initialState, reducers: { postAdded: { reducer(state, action: PayloadAction<PostStateType>) { state.posts.push(action.payload); }, prepare(title: string, content: string, userId: string) { return { payload: { id: nanoid(), date: new Date().toISOString(), title, content, user: userId, reactions: { thumbsUp: 0, hooray: 0, heart: 0, rocket: 0, eyes: 0, }, }, }; }, }, postUpdated(state, action) { const { id, title, content } = action.payload; const existingPost = state.posts.find((post : PostStateType) => post.id === id); if (existingPost) { existingPost.title = title; existingPost.content = content; } }, reactionAdded(state, action) { const { postId, reaction } = action.payload; const existingPost = state.posts.find((post : PostStateType) => post.id === postId); if (existingPost) { existingPost.reactions[reaction]++; } }, }, extraReducers(builder) { builder .addCase(fetchPosts.pending, (state) => { state.status = 'loading'; }) .addCase(fetchPosts.fulfilled, (state, action) => { state.status = 'succeeded'; // Add any fetched posts to the array state.posts = state.posts.concat(action.payload); }) .addCase(fetchPosts.rejected, (state, action) => { state.status = 'failed'; state.error = action.error.message; }) .addCase(addNewPost.fulfilled, (state, action) => { state.posts.push(action.payload); }) } }); | cs |
extraReducers(builder) {
builder
.addCase(fetchPosts.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchPosts.fulfilled, (state, action) => {
state.status = 'succeeded';
// Add any fetched posts to the array
state.posts = state.posts.concat(action.payload);
})
.addCase(fetchPosts.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
})
위와 같이 extraReducer에 파라미터인 builder를 통해 addCase를 사용하여 case를 등록해주면 됩니다.
promise 결과에 따라 pending이면 대기중, fulfilled면 성공, rejected면 실패된 상태입니다.
'React > Redux' 카테고리의 다른 글
[Redux] Redux Toolkit - A non-serializable value was detected in an action, in the path: `register` 오류 해결 (0) | 2023.07.25 |
---|---|
[Redux with TS] 새로고침해도 redux store를 유지하는 법 (0) | 2023.07.25 |
[Redux with TS] @reduxjs/toolkit nanoid에 대하여 (1) | 2023.07.21 |
[Redux with TS] connect 고차 함수와 useSelector, useDispatch (0) | 2023.07.13 |
[Redux] redux-thunk와 redux-saga란? (1) | 2023.06.08 |