RTK 기본 사용법
https://tlseoqja.tistory.com/44
이전 링크에서 RTK의 기본 사용 방법을 알아보았다.
이 코드를 TypeScript를 적용해서 사용하는 방법을 작성해보려고 한다.
타입스크립트란?
기존 자바스크립트의 단점을 보완하기 위해 개발된 정적 타입 언어(Static Type Language)이다.
자바스크립트의 확장된 언어이기때문에 자바스크립트의 모든 기능을 사용할 수 있다.
브라우저에서 실행하기 위해서 컴파일 과정을 거쳐야 한다.
더욱 자세한 내용은 아래 블로그를 참고하면 된다.
RTX & TypeScript
코드는 기존의 자바스크립트 코드와 유사하지만 타입이 추가되면서 바뀌는 부분들이 생긴다.
store.js → store.ts
// store.ts
import { configureStore } from "@reduxjs/toolkit";
import countReducer from "../slices/countSlice";
const store = configureStore({
reducer: {
count: countReducer,
}
});
// 추가
// 스토어에 등록된 reducer의 타입을 리턴받아 RootState에 선언한다.
export type RootState = ReturnType<typeof store.getState>;
// 추가
// store의 dispatch 타입을 AppDispatch에 선언한다.
export type AppDispatch = typeof store.dispatch;
export default store;
RootState 타입과 AppDispatch 타입을 추가해 준다.
RootState는 useSelector로 리덕스의 state를 조회할 때 타입을 추론해주는 용도이고,
AppDispatch는 useDispatch로 state를 변경할 수 있는 선언된 액션함수를 호출할 때 사용한다.
hooks.ts
기존 sre/store 폴더 안에 hooks.ts 파일을 하나 생성하고 아래의 코드를 작성한다.
import { useDispatch, useSelector } from "react-redux";
import type { TypedUseSelectorHook } from "react-redux";
import type { RootState, AppDispatch } from "./store";
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
기존의 react-redux의 useDispatch와 useSelector 대신 사용할 useAppSelector와 useAppDispatch를 생성해준다.
이유는 기존의 함수를 사용할 시 타입 추론이 원하는 타입으로 추론되지 않는다.
useSelector의 state undefined 타입을 가지게 되며 에러가 발생하게 되고
useDispatch는 AnyAction이란 any 타입을 추론하게 된다.
따라서 정확한 타입을 추론해서 사용하기 위해 useAppSelector와 useAppDispatch를 선언해줘야 한다.
countSlice.js → countSlice.ts
// countSlice.ts
import { createSlice } from "@reduxjs/toolkit";
// 추가
interface CountState {
value: number;
};
// 추가
const initialState: CountState = {
value: 1,
};
export const countSlice = createSlice({
name: "count",
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -=1;
}
}
});
export const { increment, decrement } = countSlice.actions;
export default countSlice.reducer;
기존 initialState의 경우 직접 객체를 넣어 value값을 설정해줬다.
이 방법을 사용해도 오류가 발생하진 않지만, 타입스크립트는 정확한 추론을 하는 것이 중요하기 때문에
따로 interface로 State의 속성을 지정해주고 State 타입의 initialState를 생성해줬다.
App.jsx → App.tsx
// App.tsx
import { store } from "./store/store";
import { useAppSelector, useAppDispatch } from "./store/hooks";
import { increment, decrement } from "./slices/countSlice";
const App = () => {
return (
<Provider store={store}>
<div class="borderLayout">
<h1>Root</h1>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
<Left1 />
<Right1 />
</div>
</div>
</Provider>
);
};
const Left1 = () => {
return (
<div class="borderLayout">
<h1>Left1</h1>
<Left2 />
</div>
);
};
const Left2 = () => {
return (
<div class="borderLayout">
<h1>Left2</h1>
<Left3 />
</div>
);
};
const Left3 = () => {
// 변경
// useAppSelector state의 값을 가져온다.
const number = useAppSelector((state) => state.count.value);
return (
<div class="borderLayout">
<h1>Left3 : {count}</h1>
</div>
);
};
const Right1 = () => {
return (
<div class="borderLayout">
<h1>Right1</h1>
<Right2 />
</div>
);
};
const Right2 = () => {
return (
<div class="borderLayout">
<h1>Right2</h1>
<Right3 />
</div>
);
};
const Right3 = () => {
// 변경
// useAppDispatch 선언하고 countSlice의 reducers에 정의된 함수를 호출한다.
const dispatch = useAppDispatch();
return (
<div class="borderLayout">
<h1>Right3</h1>
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(decrement())}>-</button>
</div>
);
};
export default App;
useAppSelector와 useAppDispatch를 사용해 생성한 변수의 타입은 아래와 같다.
참고 사이트
https://redux-toolkit.js.org/tutorials/typescript
'🖥️Frontend > React' 카테고리의 다른 글
[React] Vite를 사용해서 React 프로젝트 생성 및 실행 (0) | 2024.02.07 |
---|---|
[React] canvas & x, y좌표 값으로 길 그리기 (0) | 2023.11.28 |
[React] zustand (0) | 2023.11.18 |
[React] Redux & RTK (0) | 2023.11.17 |
[React] xlsx & file-saver & csv (0) | 2023.09.14 |
댓글