[Redux] Redux-thunk

Local Gaji·2023년 7월 10일
0

Redux

목록 보기
6/6

🔰 미들웨어란

리듀서에서 액션을 처리하여 새로운 state를 만들기 전,
미들웨어가 추가작업을 한다.

ex
1. 액션 객체를 콘솔에 출력
2. 액션을 취소, 변경시키기
3. 액션 객체를 수정하여 전달

🔰 thunk 란?

특정 작업을 함수 형태로 감싼 것

const add = () => 1 + 1;

🎈 redux-thunk

일반 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( 액션전달함수() )
  }
}    

🎈 createAsyncThunk

슬라이스의 상태를 비동기 함수로 변경하기 위해, 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 를 이용해 슬라이스에 묶어준다


🔰 1. 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.=;
            ) 
}

🔰 2. 슬라이스에 등록

/* 📄 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;
      })
  }
})

0개의 댓글