React
createAsyncThunk
sognociel
2022. 12. 22. 16:17
Redux와 비동기 코드
※ 리듀서에는 부가기능이 없는 순수 함수만 들어가야 하며 비동기 코드가 들어가서는 안된다!!!
리듀서의 목적은 상태를 편집하는 것인데, 내부에서 http 요청을 보내게 된다면 리덕스의 개념에 완전히 반대되는 일이기 때문. 동기, 비동기는 절대... 안된다...
createAsyncThunk()
비동기 작업을 처리하는 action을 만들어 주는 기능으로, redux toolkit에 내장되어있는 함수이다.
createAsyncThunk 함수를 만들면 자동적으로
비동기함수이름.pending
비동기함수이름.fulfilled
비동기함수이름.rejected
가 생성되는데, 세가지 상태별로 reducer가 필요하다.
이 세가지 상태들은 비동기적인 작업과 관련된 것으로 reducers와 별개로 extraReducers로 사용해주어야 한다.
extraReducers는 action creator를 자동적으로 만들지 못하는 것들의 집합.
아마 데이터를 받아오는 상태에 관한 것들이라고 생각하면 되는 것 같다...
데이터를 받아오는 async 함수를 Slice 외부에 생성해 준다.
const USERS_URL = "https://dummyjson.com/users";
// 유저 정보 가져오기
export const fetchUsersData = createAsyncThunk(
"users/fetchUserData",
async () => {
try {
const response = await axios.get(USERS_URL);
// fetch를 썼을 때
// const data = await response.json();
// console.log(data);
return response.data.users;
} catch (err) {
return err.message;
}
}
);
Slice
const usersSlice = createSlice({
name: "users",
initialState: {
users: [],
},
// 비동기와는 상관없는 reducer
reducers: {
loading(state) {
console.log(state);
},
},
// 비동기 reducer
extraReducers(builder) {
builder
.addCase(fetchUsersData.pending, (state, action) => {
state.status = "Loading";
})
.addCase(fetchUsersData.fulfilled, (state, action) => {
state.status = "complete";
state.users = state.users.concat(action.payload);
})
.addCase(fetchUsersData.rejected, (state, action) => {
state.status = "fail";
});
},
});
로딩했을 때 바로 유저정보를 표시하기 위해서 App.js에서 사용
import store from "./store";
import { fetchUsersData } from "./store/userSlice";
store.dispatch(fetchUsersData());
컴포넌트 내부에서 이벤트 발생시 사용 방법
// Slice 파일에서 export한 비동기 함수를 import
import {asyncUpFetch} from './counterSlice';
<button onClick={()=>{
dispatch(asyncUpFetch());
}}>+ async fetch</button><br/>