Thunk 란?
특정 작업을 나중에 할 수 있도록 미루기 위해 함수 형태로 감싼 것
예를 들어 주어진 파라미터에 1을 더하는 작업이 있다면
// 즉시 실행
const addOne = x => x + 1;
addOne(1);
// 나중에 실행
const addOneThunk = x => () => addOne(x);
setTimeOut(()=>{
addOneThunk(1) // 1초 뒤 실행
}, 1000);
addOne()
이라는 작업을 1초 뒤에 실행할 수 있도록 addOneThunk
라는 함수로 감쌌는데 이 함수를 thunk
라고 한다.
redux-thunk
미들웨어를 설치하고 추가해주여야 한다.createAsyncThunk
API 를 통해 fulfilled, rejected, pending 3가지 상태에 대해 reducer 를 작성할 수 있다.createAsyncThunk
는 redux-saga
에서만 사용할 수 있던 기능(이미 호출한 API 요청 취소하기 등)도 사용할 수 있다.createAsyncThunk(typePrefix: string, payloadCreator: AsyncThunkPayloadCreator, options?: AsyncThunkOptions): AsyncThunk
// ex
export const getRecentPosts = createAsyncThunk('posts/getRecentPosts', async () => {
const response = await axios({ baseURL: API_HOST, url: '/recentPosts' });
return (await response.data.json()) as PartialPost[];
});
createAsyncThunk
는 action creator 를 반환한다.
createSlice 의 extraReducers 함수를 이용해, builder 에 각 상황에 대한 리듀서를 추가해주어야 한다.
fulfiled 시 데이터는 action.payload 로 들어오고, rejected 시 action.error 로 들어오며 payload 는 undefined 이다.
export const PostsSlice = createSlice({
name: 'posts',
initialState,
reducers: {},
extraReducers: builder => {
builder.addCase(getRecentPosts.pending, (state) => {
state.loading = 'pending';
});
builder.addCase(getRecentPosts.fulfilled, (state, action) => {
state.loading = 'succeeded';
state.posts = action.payload;
});
builder.addCase(getRecentPosts.rejected, (state) => {
state.loading = 'failed';
});
},
});
dispatch(createAsyncThunk(..))
를 호출하여 Component 에서 액션을 dispatch 할 수 있다.
const RecentPostsPage = () => {
const dispatch = useDispatch();
const { posts, loading } = useAppSelector(state => state.postsState);
useEffect(() => {
dispatch(getRecentPosts());
}, [dispatch]);
return (
<>
<PostCardGrid posts={posts} />
{loading !== 'idle' && <PostCardGridSkeleton />}
</>
);
};
위의 예시 상황에서는
1. 컴포넌트가 마운트 되면 getRecentPosts
라는 action creator 함수를 실행한다.
1. action creator 가 pending 액션을 디스패치한다.
2. action creator 가 parameter 로 받은 payloadCreator 콜백을 호출하고, 프로미스가 반환되기를 기다린다
3. 프로미스가 반환되면,
설명이 정말 깔끔해서 이해가 잘 됩니다. 감사합니다!!