클라이언트는 서버(api) 에게 요청을 하고, 서버(api) 는 DB의 값을 받아 응답한다.
좋다. 클라이언트는 그 값을 받을 수 있다.
문제는 매번, 필요할때마다, 모든 페이지에서 서버에게 요청해 그 값을 받아올 것인가?
아니면 받아놓고, 열심히 props 전달을 통해 그 값을 앱 전역에 퍼뜨릴 것인가?
둘다 정답은 아닐 것이다. 그것이 내가 전에 했던 크나큰 실수이자, 엄청나게 느려진 반응속도를 낳게한 주범이었다.
이번에는 서버로부터 응답받은 그 값을 Redux-toolkit 의 store 에 넣고, 앱 전역에서 사용할 것이다.
React 를 사용하면서 Redux-toolkit 의 action 생성자를 통해 비동기함수를 다루어보았다.
정확히는 비동기함수를 사용가능하게 하는 action 을 통해 FireBase 의 데이터를 클라이언트의 store 로 바로 받아왔다.
이번에도 별다를 것은 없다. 다만 요청하는 곳이 내가 만든 api 일 뿐이다.
기존의 React 와 Firebase(가짜 서버)를 이용했던 경우
action 생성자를 만들어 클라이언트에서 Firebase 로 직접 요청했다.
이번에는 api 로 요청을 보내고 api 가 DB의 값을 응답할것이다.
저번시간까지 api 를 만들었다. 이번에는 Redux-toolkit 을 다룰것이다.
1. Redux-toolkit 의 설치
https://redux-toolkit.js.org/introduction/getting-started
npm install @reduxjs/toolkit
2. slice 를 만든다.
<store / sample-slice.ts>
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
export interface SampleType {
_id: string;
message: string;
}
const initialState: { sample: SampleType[] } = { sample: [] };
const sampleSlice = createSlice({
name: "sample",
initialState,
reducers: {
showSample(state) {
console.log(state.sample);
},
getSample(state, action: PayloadAction<SampleType[]>) {
state.sample = action.payload;
},
},
});
export const sampleAction = sampleSlice.actions;
export default sampleSlice.reducer;
3. index store 를 만든다.
< store / index.ts >
import { configureStore } from "@reduxjs/toolkit";
import sampleSlice from "./sample-slice";
export const store = configureStore({ reducer: { sample: sampleSlice } });
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
4. Provider 를 통해 전역에 공급한다.
< pages / _app.tsx >
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
import "../styles/globals.scss";
import { Provider } from "react-redux"; // Provider
import { store } from "@/store"; // store
export default function App({ Component, pageProps }: AppProps) {
return (
<SessionProvider session={pageProps.session}>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</SessionProvider>
);
}
5. redux-toolkit 에서 비동기함수를 처리할 action 을 만든다.
< store / sample-action.ts >
import { Dispatch } from "@reduxjs/toolkit"; // dispatch 타입
import { sampleAction } from "./sample-slice"; // store 에 저장해야하므로 저장하는 action 가져오고
import { useDispatch } from "react-redux"; // 사전정의 dispatch 를 사용할것이니 미리 불러오고
import type { AppDispatch } from "./index"; // 미리 index 에서 정의한 dispatch 타입을 가져온다.
export const sendRequest = () => { // 비동기함수 처리할 "일반함수" 생성(Hook 이 아니다)
return async (dispatch: Dispatch) => { // 반환은 dispatch 하는 함수의 결과물
const getData = async () => { // 해당 함수를 정의한다.
const response = await fetch("/api/getSample"); // 해당 함수는 서버에 요쳥하고
const responseData = await response.json();
return responseData; // 그 값을 반환하는 함수로
};
const sampleData = await getData(); // 그 값을 sampleData 에 저장하고
dispatch(sampleAction.getSample(sampleData)); // dispatch 하여 store 에 저장하는 것이 최종
};
};
export const useAppDispatch: () => AppDispatch = useDispatch;
6. 클라이언트에서 사용한다.
< pages / index.tsx >
import Head from "next/head";
import Link from "next/link";
import { useSelector } from "react-redux";
import { RootState } from "@/store";
import { useEffect } from "react";
import { useAppDispatch, sendRequest } from "@/store/sample-action"; // useAppDispatch 를 사용한다
export default function Home() {
const sample = useSelector((state: RootState) => state.sample);
const dispatch = useAppDispatch();
useEffect(() => {
dispatch(sendRequest()); // dispatch 안에는 action 에서 정의한 일반함수가 들어간다.
}, []);
console.log(sample);
return (
이로써 DB 의 값을 가져오는 api 를 통해,
해당 api 로 값을 요청하고 응답받아와 store 에 저장하는 기본 시스템이 완성되었다.
'메인-프로젝트 > Next.js - 심리검사와 강아지 프로젝트' 카테고리의 다른 글
6. SASS, @for 과 @if 를 활용한, 스타일링 지정 (0) | 2023.02.03 |
---|---|
5. POST 를 이용한 데이터 가져오기, 로컬스토리지에 저장하기 (0) | 2023.02.03 |
3. DB의 데이터를 fetch - "API" 를 통한 GET 과 "사전 데이터페칭"을 통한 GET (0) | 2023.01.28 |
2. MongoDB 연결과 API 를 통한 fetch(1) - MongoDB 연결 (0) | 2023.01.28 |
1. Google OAuth 구현하기 [TypeScript + Next.js + Next-auth] (1) | 2023.01.27 |
댓글