DB 에 있는 값을, Store 로 직접 가져오는 Thunk 액션 생성자를 사용해본다.
준비물
typescript
react-redux
redux-toolkit
데이터베이스 서버
서버
1. Slice 의 생성
store 폴더 안에 slice 를 생성한다.
< store / user-diary-slice.ts >
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
export interface TypeUserDiary { // 타입 지정
_id: string; // mongodb 자동
userEmail: string;
diaryTitle: string;
diaryContent: string;
feeling: number;
date: string;
}
const initialState: { userDiaryData: TypeUserDiary[] } = { userDiaryData: [] }; // 초기값
const userDiarySlice = createSlice({ // 슬라이스 생성
name: "userDiary",
initialState,
reducers: {
putUserDiary(state, action: PayloadAction<TypeUserDiary[]>) { // reducer 설정
state.userDiaryData = action.payload;
},
},
});
export const userDiaryAction = userDiarySlice.actions;
export default userDiarySlice.reducer;
주의사항
1. payload 타입의 지정
2. store 의 생성
store 폴더의 index.ts 안에 store 를 생성한다.
< store / index.ts >
import { configureStore } from "@reduxjs/toolkit";
import userDiarySlice from "./user-diary-slice";
export const store = configureStore({
reducer: { userDiary: userDiarySlice },
});
export type RootState = ReturnType<typeof store.getState>; // select 하기위한 RootState 타입
export type AppDispatch = typeof store.dispatch; // Dispatch 를 위한 AppDispatch 타입
주의사항
1. Root State 의 타입을 지정하고 export
2. AppDispatch 의 타입을 지정하고 export
3. store 의 등록
메인 파일에 react-redux 를 통해, store 를 등록, 제공한다.
< index.tsx >
...
import { Provider } from "react-redux";
import { store } from "./store/index";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<React.StrictMode>
<Provider store={store}> // store 등록
<BrowserRouter>
<Layout>
<App />
</Layout>
</BrowserRouter>
</Provider>
</React.StrictMode>
);
4. action 의 생성
slice 안의 reducer 함수에는 순수함수만을 사용할 수 있다.
순수함수가 아닌 비동기함수(fetch) 를 사용하기 위해,
비동기 함수를 처리할 action 을 따로 정의해 사용하도록 한다.
그것이 Thunk 액션 생성자이다.
store 폴더 안에 action 을 정의한다.
< store / user-diary-slice.ts >
import { Dispatch } from "@reduxjs/toolkit"; // action 을 실행시키기 위한, Dispatch 의 타입을 가져온다.
import { userDiaryAction } from "./user-diary-slice";// store 에 저장하기 위해(action 실행), slice 에서 저장한 action 가져온다.
import { useDispatch } from "react-redux"; // useDispath 의 사전 생성
import type { AppDispatch } from "./index"; // action 생성자용 Dispatch 타입
export const getRequest = (userEmail: string) => { // 1. 일반함수 생성(파라미터는 자유)
return async (dispatch: Dispatch) => { // 2. 일반함수는 비동기함수를 반환한다.
const getUserDiaryData = async () => { // 3. 반환되는 함수 안에 실제 fetch할 함수를 생성
const response = await fetch(
`http://localhost:5000/api/diary/${userEmail}`
);
const responseData = await response.json();
return responseData.data;
};
const userDiaryData = await getUserDiaryData(); // 4. fetch할 함수를 실행시키고
dispatch(userDiaryAction.putUserDiary(userDiaryData)); // 5. dispatch를 진행하여, store 에 저장
};
};
export const useAppDispatch: () => AppDispatch = useDispatch;// 6. 컴포넌트에서 사용할 dispatch 타입 지정
주의사항
1. export 하는 함수는 "일반함수"이다. async 를 사용하는 실수를 조심하자.
2. 마치 useEffect 안에서, 비동기함수를 실행시키는 것 처럼
일반함수에서 비동기함수를 정의하고, 실행시키고, store 에 넣는 형태를 가진 일반함수인 것이다.
그리고 정의된 일반함수(정의한 최상단 일반함수 - getRequest) 를 컴포넌트에서 실행시키는 것 뿐이다.
3. AppDispatch 의 타입을 지정하고 export 할것.
5. 컴포넌트 내에서 액션 생성자의 사용
사용법은 단순하다.
1. action 생성자를 만들때, 사전 정의한 useAppDispatch 를 통해, dispatch 하고
2. react-redux 의 dispatch 처럼, dispatch( ... ) 처럼 사용하면된다.
< App.tsx >
import { useEffect } from "react";
import { useAppDispatch, getRequest as getRequestForDiary } from "./store/user-diary-action";
import { useSelector } from "react-redux";
import { RootState } from "./store";
let initial = true;
function App() {
const dummyuUserEmail = "mms@ms.com"; // 추후 OAuth 로 변경
const dispatch = useAppDispatch();
const userDiaryData = useSelector( // 단순 확인용 ( 여기서 필요 없음 )
(state: RootState) => state.userDiary.userDiaryData
);
useEffect(() => {
if (initial) {
initial = false;
return;
}
dispatch(getRequestForDiary(dummyuUserEmail)); // 유저 EMAIL 을 인수로
}, []);
return (
<div className="App">
...
'메인-프로젝트 > MERN - 다이어리 프로젝트' 카테고리의 다른 글
10. [ Oauth, Node.js, React] Naver Oauth 로 로그인하기 - (2) 코드 (0) | 2023.02.24 |
---|---|
9. [ Oauth, Node.js, React] Naver Oauth 로 로그인하기 - (1) 이론 (0) | 2023.02.23 |
7. [서버] 서버설정 (2) - Validation 아웃소싱과 DB 연결, 사용까지 (0) | 2023.02.21 |
6. [서버] 서버설정 (1) - 기본부터 라우터와 컨트롤러, 오류처리까지 (0) | 2023.02.21 |
5.[클라이언트] - WEB SPEECH API 기반, 음성 인식 라이브러리 사용하기 (0) | 2023.02.21 |
댓글