TIL : 최종프로젝트 5일차

hihyeon_cho·2023년 2월 11일
0

TIL

목록 보기
68/101

서버state관리를 React-Query로 하려고 했지만, 상태관리를 redux로 함에 따라 전역 상태관리 역시 RTK로 일괄적으로 관리하는 게 낫다고 판단해 이번 프로젝트에서 RTK-Query를 이용하기로 했다.

redux에 react-query가 합쳐진 것 같아 익숙한 것 같으면서도 그래도 다른 부분들이 있어 공부하면서 마냥 간단히 적용할 수는 없었다. RTK-Query는 api요청으로 데이터를 받아오는 것이 기준인데, 우리 팀은 firestore로 작업 중이기 때문이다. 그래서 RTK-Query 쓰는 방법과 데이터를 post하는 것 까지만 구현되어서 그 내용에 대해 작성해보려고 한다.

RTK-Query

(참고자료 : 공식홈페이지, 블로그 )
: RTK 쿼리는 React Query , SWR , Apollo 및 Urql 과 같은 라이브러리에서 대중화된 API 디자인 패턴 및 기능 개념을 기반으로 하여, Redux의 고유한 강점과 기능을 활용할 수 있다.
api요청으로 데이터를 받아와서 바로 store에 저장하기 때문에 기존 redux에 비해 적은 양의 코드로 state관리가 가능하며, Redux Toolkit에 내장되어 있어 따로 설치할 필요가 없다.
여러 endpoint가 있는 "API Slice"를 정의해서 하나의 중앙위치에서 작업을 수행할 수 있다.

설치하기

: redux-toolkit 설치하면 안에 내장되어 있다.
yarn add react-redux @reduxjs/toolkit

사용하기

1. apiSlice.ts파일을 생성하여, createAPi로 서버의 기본 URL과 상호작용할 엔드포인트를 나열하는 "API Slice"를 정의한다.

2. fetchBaseQuery는 요청을 단순화하기 위한 Wrapper라고한다. 보통()안에 api주소를 넣는다.
하지만, 데이터를 firestore에서 받아오기 때문에 따로 받아오는 api주소가 없으므로, 빈칸으로 두었다. ( 구현할 때 참고한 포스팅 )

3. tagType을 정의한다.

4. endpoints안에 필요한 reducer들을 작성해주면 된다.

5. use{reducer이름}{Query or Mutation} hook을 export 해주면 된다.

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { addDoc, collection } from "firebase/firestore";
import { dbService } from "../../utils/firebase";

export const courseApi = createApi({  // 1
  baseQuery: fetchBaseQuery(),  // 2
  tagTypes: ["Courses"],  // 3
  endpoints: (builder) => ({
    addCourse: builder.mutation({  //4
      async queryFn(newCourse) {
        try {
          await addDoc(collection(dbService, "courses"), newCourse);
          return { data: newCourse };
        } catch (error: any) {
          console.error(error.message);
          return { error: error.message };
        }
      },
      invalidatesTags: ["Courses"],
    }),
  }),
});

export const {useAddCourseMutation} = courseApi; // 5

6.   configStore.ts 내용도 아래처럼 변경해준다.

import { configureStore } from "@reduxjs/toolkit";
import { courseApi } from "../modules/apiSlice";

const store = configureStore({
  reducer: {
    [courseApi.reducerPath]: courseApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(courseApi.middleware),
});

export default store;

❓댓글 CRUD를 구현하면서 댓글에 대한 reducer들은 파일을 따로 분리하여 관리하고 싶었다. 그래서 commentSlice.ts파일을 추가한 후,
위 코드의 reducer:{} 안에
[commentApi.reducerPath]: commentApi.reducer,
middleware 내용에 하나 이상의 Api를 작성하려고 구글링해서 검색된 적용방법들을 전부 적용해봤는데, 자꾸 컴파일오류가 떴었다.

❗️구글링 하다보니 일반적으로 애플리케이션이 통신해야 하는 기본 URL당 하나의 API 슬라이스만 있어야 하기 때문에 어쩔 수 없이 하나의 API 슬라이스 안에서 course의 reducer들이랑 comment의 reducer들을 같이 관리해야 할 것 같다.

7.   index.tsx 파일에서 최상위에 <ApiProvider>컴포넌트를 위치시켜 <Provider>를 감싸준다.

import { Provider } from "react-redux";
import store from "./redux/config/configStore";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";
import { ApiProvider } from "@reduxjs/toolkit/dist/query/react";
import { courseApi } from "./redux/modules/apiSlice";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <ApiProvider api={courseApi}>
    <Provider store={store}>
      <App />
    </Provider>
  </ApiProvider>
);

8.   reducer를 사용할 파일에서 apiSlice.ts파일에서 export했던 use{reducer이름}{Query or Mutation} hook을 import한다.

9.   use{reducer이름}{Query or Mutation}로 액션을 만들어 준다.

10. 필요한 곳에서 액션을 실행시켜준다.
( 8, 9, 10 참고 블로그 )

import { useAddCourseMutation } from "../redux/modules/apiSlice"; // 8

const Post = () => {
const [addCourse] = useAddCourseMutation(); // 9
   const submitHandle = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    .
    .
    .
    const newPost = {
      category,
      selectedValues,
      title,
    };
    addCourse(newPost); // 10
  };
   return (
    <form onSubmit={submitHandle}>
       .
       .
       .
    </form>
  );
};

Post작업은 이렇게 해결할 수 있었다. get, update, delete 작업도 자료들 참고해가면서 잘 구현해봐야겠다 !

profile
코딩은 짜릿해 늘 새로워 ✨

0개의 댓글