티스토리 뷰
[ Builder Callback 표기법 ]
redux toolkit - thunk 를 이용해서 비동기 작업을 처리하는 방법 by 생활코딩
- 전체 코드
const status = useSelector(state => {
return state.counter.status;
});
const count = useSelector(state => {
return state.counter.value;
});
<button onClick={() => {
dispatch(asyncUpFetch());
}}>+ async thunk</button>
<div>{count} | {status}</div>
const asyncUpFetch = crateAsynckThunk(
'counterSlice/asyncUpFetch',
async() => {
const resp = await fetch('httpsL//~')
const data = await resp.json();
return data.value;
}
)
const counterSlice = createSlice({
name:'counterSlice',
initialState{
value:0,
status:'Welcome'
},
extraReducers:(builder)=>{
builder.addCase(asyncUpFetch.pending, (state,action) => {
state.status = 'Loading';
})
builder.addCase(asyncUpFetch.fulfiled, (state,action) => {
state.value = action.payload;
state.status = 'complete';
})
builder.addCase(asyncUpFetch.rejected, (state,action) => {
state.status = 'fail';
})
}
})
☆ createAsyncThunk는 비동기 작업을 처리하는 action을 만들어준다!
const asyncUpFetch = crateAsynckThunk(
'counterSlice/asyncUpFetch',
async() => {
const resp = await fetch('httpsL//~')
const data = await resp.json();
return data.value;
}
)
1.
'counterSlice/asyncUpFetch',
첫 번째 타입을 적은 것
2.
async() => {
const resp = await fetch('httpsL//~')
const data = await resp.json();
return data.value;
}
액션이 실행 됐을 때 처리되어야 하는 작업
: 서버에 접속 - 결과 가져오기 - 결과 리턴하기
두 번째 파라미터에 이 작업을 함수로서 전달함
✔️ action creator는 아래와 같이 3가지 상태를 갖습니다.
- action creator.pending는 대기상태를 의미합니다.
- action creator.fulfilled 는 완료 상태를 의미합니다.
- action creator.rejected는 오류 상태를 의미합니다.
*createAsyncThunk를 쓰면 자동으로 만들어지는 상수
📌 위의 세가지 상태 별로 reducer가 필요함. 이 reducer를 어디다 주나?
const counterSlice = createSlice({
name:'counterSlice',
initialState{
value:0,
status:'Welcome'
},
extraReducers:(builder)=>{
builder.addCase(asyncUpFetch.pending, (state,action) => {
state.status = 'Loading';
})
builder.addCase(asyncUpFetch.fulfiled, (state,action) => {
state.value = action.payload;
state.status = 'complete';
})
builder.addCase(asyncUpFetch.rejected, (state,action) => {
state.status = 'fail';
})
}
})
createSlice 에서 extraReducers 의 builder.addCase()를 통해서 각 상태일 때 동작할 reducer를 두 번째 파라미터의 함수로 전달
✔️ thunk는 각각의 상태에 따른 reducer를 체계적으로 작성할 수 있도록 유도합니다.
thunk를 처리할 때는 extraReducers를 사용합니다.
동기적 액션에는 reducers를, 비동기적인 작업에는 extraReducers를 사용하는데,
reducers로 동기 작업을 할 때는 리덕스 툴킷이 action creator를 자동으로 만들어주는 반면
extraReducers로 비동기 작업을 할 때는 툴킷이 action creator를 자동으로 만들지 못한다.
그래서 비동기 작업을 할 때는 extraReducers 안에서 action creator를 정의해 준다.
[Map Object 표기법]
*생활코딩 강의 내용을 todoSlice.js 에 적용하면
// 완성된 Thunk 함수
export const __getTodos = createAsyncThunk(
"todos/getTodos",
async (payload, thunkAPI) => {
try {
const data = await axios.get("<http://localhost:3001/todos>");
console.log(data);
} catch (error) {
console.log(error);
}
}
);
1.
"todos/getTodos",
첫 번째 타입을 적은 것
2.
async (payload, thunkAPI) => {
try {
const data = await axios.get("<http://localhost:3001/todos>");
console.log(data);
} catch (error) {
console.log(error);
}
}
액션이 실행 됐을 때 처리되어야 하는 작업
: 서버에 접속 - 결과 가져오기 - 결과 리턴하기
두 번째 파라미터에 이 작업을 함수로서 전달함
📌 위의 세가지 상태 별로 reducer가 필요함. 이 reducer를 어디다 주나?
export const todosSlice = createSlice({
name: "todos",
initialState,
reducers: {},
extraReducers: {
[__getTodos.pending]: (state) => {
state.isLoading = true; // 네트워크 요청이 시작되면 로딩상태를 true로 변경합니다.
},
[__getTodos.fulfilled]: (state, action) => {
state.isLoading = false; // 네트워크 요청이 끝났으니, false로 변경합니다.
state.todos = action.payload; // Store에 있는 todos에 서버에서 가져온 todos를 넣습니다.
},
[__getTodos.rejected]: (state, action) => {
state.isLoading = false; // 에러가 발생했지만, 네트워크 요청이 끝났으니, false로 변경합니다.
state.error = action.payload; // catch 된 error 객체를 state.error에 넣습니다.
},
},
http://blog.hwahae.co.kr/all/tech/tech-tech/6946/
https://www.youtube.com/watch?v=K-3sBc2pUJ4&ab_channel=%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9