TIL36-01 Thunk 심화

김태혁·2023년 2월 18일
0

TIL

목록 보기
114/205

Thunk 구현하기

(1) Thunk 함수 구현 : 서버에서 데이터 가져오기, 가져온 데이터 Store로 dispatch 하

  • initialState 에 다음을 추가한다.
  • isLoading은 서버에서 todos를 가져오는 상태를 나타내는 값. 초기값은 false이고, 서버와 통신이 시작되면 true였다가 통신이 끝나면 다시 false로 변경된다.
  • isError는 서버와의 통신이 실패한 경우 true로 변경된다.
  • error는 만약 서버와의 통신이 실패한 경우 서버에서 어떤 에러 메시지를 보내준다. 그것을 담아놓는 값. 초기에는 에러가 없기때문에 null로 지정한다.
// src/redux/modules/todosSlice.js
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";

const initialState = {
  todos: [],
  isLoading: false,
  isError: false,
  error: null,
};

// 우리가 추가한 Thunk 함수
export const __getTodos = createAsyncThunk(
  "getTodos",
  (payload, thunkAPI) => {}
);

export const todosSlice = createSlice({
  name: "todos",
  initialState,
  reducers: {},
  extraReducers: {}, 
});

export const {} = todosSlice.actions;
export default todosSlice.reducer;
  • thunk 함수를 아래와 같이 작성한다. const response는 Promise를 반환한다.
  • 다시 말해 axios.get() (함수)은 Promise를 반환합니다. 그래서 반환된 Promise의 fullfilled 또는 rejected된 것을 처리하기위해 async/await 을 추가했다.
  • 이 요청이 성공하는 경우에 실행되는 부분과 실패했을 때 실행되어야 하는 부분을 나누기 위해 try..catch 구문을 사용했다.
export const __getTodos = createAsyncThunk('getTodos', async (payload, thunkAPI) => {
  try {
	const response = 
  await axios.get('http://localhost:4000/todos');
        //Promise -> resolve (= 네트워크 요청이 성공한 경우) ->dispatch해주는 기능
	   return thunkAPI.fulfillWithValue(response.data);
} catch (error) {
	     return thunkAPI.rejectWithValue(error);
    }
});
  • fulfillWithValue는 툴킷에서 제공하는 API 이다.

  • Promise에서 resolve된 경우, 다시 말해 네트워크 요청이 성공한 경우에 dispatch 해주는 기능을 가진 API 이다. 그리고 인자로는 payload를 넣어줄 수 있다.

  • rejectWithValue 도 툴킷에서 제공하는 API 이다.

  • Promise가 reject 된 경우, 네트워크 요청이 실패한 경우 dispatch 해주는 기능을 가진 API다. 마찬가지로 인자로 어떤 값을 넣을 수 있습니다. catch 에서 잡아주는 error 객체를 넣었다.

(2) 리듀서 로직 구현 → extraRecuders

  • Slice 내부에 있는 extraRecuders에서 아래와 같이 코드를 구한다.
  • pending, fulfilled, rejected에 대해 각각 어떻게 새로운 state를 반환할 것인지 구현할 수 있다
  • thunk 함수에서 thunkAPI.fulfillWithValue(response.data) 라고 작성하면 [ __getTodos.fulfilled ] 이 부분으로 디스패치가 된다.
  • action을 콘솔에 찍어보면 fulfillWithValue(response.data) 가 보낸 액션객체를 볼 수 있다. typepayload가 있다
export const todoSlice = createSlice({
    name: 'todos',
    initialState,
    reducers: {},
    extraReducers: {
        [__getTodos.pending]: (state, action) => {
            state.isLoading = true;
            state.isError = false;
        },
        [__getTodos.fulfilled]: (state, action) => {
            state.isLoading = false;
            state.isError = false;
            state.todos = action.payload;
        },
        [__getTodos.rejected]: (state, action) => {
            state.isLoading = false;
            state.isError = true;
            state.error = action.payload;
        },
    },

});

(3) Store값 조회하고, 화면에 렌더링 하기

  • data를 가져오는 동안에는 우리의 서비스를 사용하는 유저에게 ‘로딩중' 임을 한다.
  • 만약에 네트워크가 실패해서 정보를 가져오지 못한 경우, 에러 메시지를 보여준다.
  • 위 두가지가 모두 아닌 경우에는 서버에서 불러온 todos를 화면에 보여준다.
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import './App.css';
import { __getTodos } from './modules/todoSllice'; 

function App() {
    const dispatch = useDispatch();
    const { isLoading, error, todos } = useSelector((state) => {
        return state.todos;
    });
    useEffect(() => {
        dispatch(__getTodos());
    }, []);
    if (isLoading) {
        return <div>로딩중...</div>;
    }
    if (error) {
        return <div>{error.message} </div>;
    }
    return (
        <div>
            {todos.map((todo) => {
                return <div key={todo.id}>{todo.title}</div>;
            })}
        </div>
    );
}  
export default App;
profile
도전을 즐기는 자

0개의 댓글