Redux 의 Reducers 함수는 다음과 같은 조건이 있습니다.
순수함수여야 하며, 사이트 이펙트에 영향을 받지 않아야 하고, 동기적인 코드여야만 한다는
조건이 바로 그것입니다.
이는 react 의 useReducer 함수도 같은 조건입니다.
그럼 Redux 사용시, 이런 비동기 코드는 어디에서 작성해야하는 걸까요?
3가지 방법이 있습니다.
1. 컴포넌트 내에 useEffect() 함수를 사용하여 직접 정의
2. 사용자 정의 action 을 사용( 커스텀 액션 생성자 (Thunk) )
3. createAsyncThunk 사용( redux toolkit 만 가능)
1. 비동기 코드 예시
1-1. 컴포넌트 내에 useEffect() 함수를 사용하여 직접 정의
const Component = () => {
const dispatch = useDispatch();
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('api/data');
const data = await response.json();
dispatch(dataActions.setData(data));
} catch (error) {
dispatch(dataActions.setError(error.message));
}
};
fetchData();
}, [dispatch]);
}
1-2. 사용자 정의 action 을 사용( 커스텀 액션 생성자 (Thunk) )
Redux Toolkit 을 이미 설치 했다면 추가 설치는 필요 없습니다
// dataSlice.js
const dataSlice = createSlice({
name: 'data',
initialState: {
// 생략
},
reducers: {
// 생략
}
});
export const fetchData = () => {
return async (dispatch) => { // 설명 2 하단 참조
try {
const response = await fetch('api/data');
const data = await response.json();
dispatch(dataActions.setData(data));
} catch (error) {
dispatch(dataActions.setError(error.message));
}
};
};
// Component.js
const Component = () => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchData()); // 설명 1 하단 참조
}, [dispatch]);
}
설명 1 ) 기존의 dispatch 는 객체로 된 action을 넘겨줘야 하지만함수를 넣어줄 경우 자동으로 thunk 라이브러리가
작동하면서 설명2) 의 async () 함수의 인자에 자동으로 dispatch 함수를 넣어주어 비동기 코드 전후로 state 값을 변경 요청할 수 있게 된다 (dispatch)
그리고 1-1 과는 다르게 component 안에서 직접 코드를 두는 게 아닌 store 파일들의 createSlice 함수 블럭의
밖에서 비동기 코드를 사용하게 된다
1-3. createAsyncThunk 사용
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
export const fetchData = createAsyncThunk(
'data/fetchData',
async () => {
const response = await fetch('api/data');
return response.json();
}
);
const dataSlice = createSlice({
name: 'data',
initialState: { data: null, status: 'idle', error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchData.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchData.fulfilled, (state, action) => {
state.status = 'succeeded';
state.data = action.payload;
})
.addCase(fetchData.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
},
});
2. 각 방법의 장단점
2-1 useEffect 방식
장점: 구현이 간단함
단점: 비즈니스 로직이 컴포넌트에 존재
2-2 커스텀 액션 생성자
장점: 비즈니스 로직을 리덕스 파일에서 관리
단점: 에러 처리가 복잡할 수 있음
2-3 createAsyncThunk
장점:
로딩, 성공, 실패 상태 자동 관리
타입스크립트 지원이 우수
에러 처리가 체계적
단점:
초기 설정이 다소 복잡
학습 곡선이 있음
'React' 카테고리의 다른 글
[React] React Router의 Form vs useFetcher().Form (0) | 2024.11.13 |
---|---|
[React] React Router의 useNavigation 훅 - state와 주요 속성 (0) | 2024.11.12 |
[React] Redux와 Redux Toolkit 비교 및 구현 방법 (0) | 2024.11.08 |
[React] Redux: App-Wide State와 Cross-Component State 관리 가이드 (0) | 2024.11.07 |
[React] useReducer vs useState: 언제 어떤 Hook을 사용해야 할까?" (0) | 2024.11.06 |