[React] Redux-thunk 이해하기

JIOO·2022년 6월 13일
0

React

목록 보기
5/18
post-thumbnail

👨‍🎓 Redux-thunk를 이해하기 위해 이래저래 문서를 찾다가 벨로퍼트님의 모던 리액트를 보며 공부했다, 그중 Promise를 이용한 Redux-thunk를 보는데 처음 보는 입장에서 이게 무슨말인지를 몇시간동안 되새기다가 풀이를 써볼려고 글을 쓴다.

Redux-thunk 로 프로미스 다루기 : 참조 (벨로퍼트님)

👩‍💻 우선 뭘 할꺼냐면 더미데이터 API를 만들어서 요청&겟 한 다음 VIEW에 뿌려줄거다.

1. 더미데이터 API준비

// 데미데이터 목록
	const posts = [
  	  {
    	id: 1,
    	title: '리덕스 미들웨어를 배워봅시다',
    	body: '리덕스 미들웨어를 직접 만들어보면 이해하기 쉽죠.'
  	 },
  	 {
    	id: 2,
    	title: 'redux-thunk를 사용해봅시다',
    	body: 'redux-thunk를 사용해서 비동기 작업을 처리해봅시다!'
 	 },
  	 {
    	id: 3,
    	title: 'redux-saga도 사용해봅시다',
    	body:'나중엔 redux-saga를 사용해서 비동기 작업을 처리하는 방법도 배워볼 거예요.'
  	 }
  ];

1-1 더미데이터를 조회 할 함수들

const sleep = n => new Promise(resolve => setTimeout(resolve, n));
// n 시간동안 딜레이를 주는 프로미스를 만들어주는 함수 (0.5초)
// 0.5초 딜레이를 줘서 실행이 겹치는 걸 막는 것 같다.

// 포스트 목록 전체를 가져오는 비동기 함수
export const getPosts = async () => {
  await sleep(500); // 0.5초 쉬고
  return posts; // posts 배열
};

// ID로 포스트를 조회하는 비동기 함수
export const getPostById = async id => {
  await sleep(500); // 0.5초 쉬고
  return posts.find(post => post.id === id); // id 로 찾아서 반환
};

2. 리덕스로 더미데이터를 조회 할 수 있는 모듈을 만든다.

👨‍🎓 리덕스 쓸 때 필요한 것들


  • initialState 만들기
  • 액션타입 설정
  • 액션 생성함수 만들기
  • 리듀서 생성
  • createstore에 reducer 넣기 (여기선 맨 마지막에)

import * as postsAPI from '../api/posts'; 
// api/posts 안의 함수 모두 불러오기


/* initialState 설정 */

const initialState = {
  posts: {
    loading: false,
    data: null,
    error: null
  },
  post: {
    loading: false,
    data: null,
    error: null
  }
};

/* 액션 타입 */

// 포스트 여러개 조회하는 액션타입들 
const GET_POSTS = 'GET_POSTS'; // 요청 시작
const GET_POSTS_SUCCESS = 'GET_POSTS_SUCCESS'; // 요청 성공
const GET_POSTS_ERROR = 'GET_POSTS_ERROR'; // 요청 실패

// 포스트 하나 조회하는 액션타입들
const GET_POST = 'GET_POST';
const GET_POST_SUCCESS = 'GET_POST_SUCCESS';
const GET_POST_ERROR = 'GET_POST_ERROR';

/* 액션 생성함수 작성 */

export const getAllPostRequest = () => async dispatch => {
  dispatch({ type: GET_POSTS }); // 요청이 시작됨
  //async를 쓰는 이유는 요청을 시작하고 postsAPI.getPosts()를 실행해야하기 때문
  try {
    const posts = await postsAPI.getPosts(); // API 호출
    dispatch({ type: GET_POSTS_SUCCESS, posts }); // 성공
  } catch (e) {
    dispatch({ type: GET_POSTS_ERROR, error: e }); // 실패
  }
};

export const findPostRequest = id => async dispatch => {
  dispatch({ type: GET_POST }); // 요청이 시작됨
  try {
    const post = await postsAPI.getPostById(id); // API 호출
    dispatch({ type: GET_POST_SUCCESS, post }); // 성공
  } catch (e) {
    dispatch({ type: GET_POST_ERROR, error: e }); // 실패
  }
};

/* 액션 생성함수 작성 end */

/* 리듀서 작성 */

export default function posts(state = initialState, action) {
  switch (action.type) {
    case GET_POSTS:
      return {
        ...state,
        posts: {
          loading: true,
          data: null,
          error: null
        }
      };
    case GET_POSTS_SUCCESS:
      return {
        ...state,
        posts: {
          loading: true,
          data: action.posts,
          error: null
        }
      };
    case GET_POSTS_ERROR:
      return {
        ...state,
        posts: {
          loading: true,
          data: null,
          error: action.error
        }
      };
    case GET_POST:
      return {
        ...state,
        post: {
          loading: true,
          data: null,
          error: null
        }
      };
    case GET_POST_SUCCESS:
      return {
        ...state,
        post: {
          loading: true,
          data: action.post,
          error: null
        }
      };
    case GET_POST_ERROR:
      return {
        ...state,
        post: {
          loading: true,
          data: null,
          error: action.error
        }
      };
    default:
      return state;
  }
}

CreateStore에 넣기

const store = createStore(reducer명)

화면에 뿌리기

const propsData = useSelector((state) => state.posts.데이터명); // 조회 한 후 map처리

📋 결과물

profile
프론트엔드가 좋은 웹쟁이

0개의 댓글