리듀서에서 액션을 처리하여 새로운 state를 만들기 전,
미들웨어가 추가작업을 한다.
ex
1. 액션 객체를 콘솔에 출력
2. 액션을 취소, 변경시키기
3. 액션 객체를 수정하여 전달
특정 작업을 함수 형태로 감싼 것
const add = () => 1 + 1;
일반 Redux 에서는 액션 크리에이터가 액션 객체
를 dispatch 한다
const actionCreator = (payload) => ({action: '액션명', payload});
redux-thunk
를 사용하면 액션 객체 대신 함수를 리턴할 수 있다.
함수의 실행이 끝난 다음 액션 값이 전달되므로, 비동기 작업을 할 수 있다.
/* 1초 뒤 실행시키기 */
const 액션전달함수 = () => {
return { type: 액션타입 }
}
const actionCreator = () => {
return (dispatch) => {
setTimeout( () => { dispatch(액션전달함수()) }, 1000 );
};
}
dispatch( actionCreator ) // 1초뒤 실행
/* 현재 상태 값에 따라 액션 취소시키기 */
const actionCreator = () => {
return (dispatch, getState) => {
const 현재상태 = store.getState()
if (현재상태 === 0) {
return
}
dispatch( 액션전달함수() )
}
}
슬라이스의 상태를 비동기 함수로 변경하기 위해, Redux Toolkit 에서 제공하는 함수
export const 이름 = createAsyncThunk(
type명,
async () => { 비동기함수 }
)
이때 비동기함수
가 return 하는 값이 payload 객체가 된다.
export const getData = createAsyncThunk(
"GET/DATA",
async () => {
const response = await axios.get("url")
return response.data
}
)
/* 또는 */
export const getData = createAsyncThunk(
"GET/DATA",
async () => {
return axios.get("url")
.then(response => response.data)
}
)
createAsyncThunk
로 생성한 비동기 함수는 3가지의 thunk Action Creator 를 반환한다.
1. getData.pending
2. getData.fulfilled
3. getData.rejected
아래의 순서대로 dispatch 된다.
1. pending action을 dispatch
2. 비동기함수 호출
3. promise 반환되기를 기다림
4. promise 반환됨
5. 응답 성공시 fulfilled action / 실패시 rejected action 을 dispatch
6. dispatch된 액션을 담고있는 fulfilled promise 반환
위에서 만든 getData
AsyncThunk 함수를
extraReducers
를 이용해 슬라이스에 묶어준다
슬라이스를 생성할때 createSlice
의 옵션에 extraReducer
를 지정해주어, 외부 비동기 함수를 슬라이스와 연결한다.
이 비동기 함수의 pending
fulfulled
rejectd
상태에 대한 액션이 생성된다.
extraReducers: (builder) => {
builder
.addCase(getData.pending, (state, action) =>
// 특정 값 지정 또는 action.payload 값 사용
state.키 = 값;
)
.addCase(getData.fulfilled, (state, { payload }) =>
state.키 = 값;
)
.addCase(getDate.rejected, (state, { payload }) =>
state.키 = 값;
)
}
/* 📄 src/reducers/기능Slice.js */
const initialState = {
loading: false,
error: null,
data: null,
}
export const 기능Slice = createSlice({
name: '기능',
initialState,
extraReducers: (builder) => {
builder
.addCase(getData.pending, (state) => {
state.loading = true;
})
.addCase(getData.fulfilled, (state) => {
state.loading = false;
state.data = action.payload;
})
.addCase(getData.rejected, (state) => {
state.loading = false;
state.error = action.payload;
})
}
})