React + TypeScript2 Redux toolkit
25 Apr 2023 | typeScript코딩애플강의를 보고 정리했습니다. 코드위주로 정리했습니다.
리덕스는 state를 한 곳에서 관리할 수 있어서, 컴포넌트들이 props없이 state를 다루기 쉽고, 수정방법을 미리 reducer라는 함수로 정의해놔서 state수정시 발생하는 버그를 줄일 수 있어서 쓴다.
그럼 리덕스를 사용할때 타입은 어떻게 적용해줄까?
전통방식의 redux
npm install redux react-redux
import { Provider } from 'react-redux';
import { createStore } from 'redux';
interface Counter {
count: number;
}
const 초기값: Counter = { count: 0 };
// action:any 라고 임의로 채운것임
function reducer(state = 초기값, action: any) {
if (action.type === '증가') {
return { count: state.count + 1 };
} else if (action.type === '감소') {
return { count: state.count - 1 };
} else {
return initialState;
}
}
const store = createStore(reducer);
// store의 타입 미리 export 해두기
export type RootState = ReturnType<typeof store.getState>;
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
(전통방식 redux) state를 꺼낼 때
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Dispatch } from 'redux';
import { RootState } from './index';
function App() {
// useSelector()파라미터에 타입지정
const 꺼내온거 = useSelector((state: RootState) => state);
// 타입지정
const dispatch: Dispatch = useDispatch();
return (
<div className='App'>
{꺼내온거.count}
<button
onClick={() => {
dispatch({ type: '증가' });
}}
>
버튼
</button>
<Profile name='kim'></Profile>
</div>
);
}
(신규방식 redux) state와 reducer 만들 때 타입지정 필요
npm install @reduxjs/toolkit
import { createSlice, configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
const 초기값 = { count: 0, user: 'kim' };
const counterSlice = createSlice({
name: 'counter',
initialState: 초기값,
reducers: {
increment(state) {
state.count += 1;
},
decrement(state) {
state.count -= 1;
},
incrementByAmount(state, action: any) {
state.count += action.payload;
},
},
});
let store = configureStore({
reducer: {
counter1: counterSlice.reducer,
},
});
//state 타입을 export 해두는건데 나중에 쓸 데가 있음
export type RootState = ReturnType<typeof store.getState>;
//수정방법 만든거 export
export let { increment, decrement, incrementByAmount } = counterSlice.actions;
(1) state 초기값 타입지정 알아서 지정
(2) reducer 안의 action 파라미터의 타입지정
(3) 나머지는 타입지정 자동으로 된다.
action 타입지정은 방법이 따로있다.
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
(상단 생략)
incrementByAmount (state, action: PayloadAction<number>){
state.value += action.payload
},
나중에 dispatch할 때 보내는 데이터가 있으면, 그걸 payload라고 하는데
그 자료의 타입을 <>
안에 집어넣어서 타입지정하라는 소리이다.
예를들어 문자를 payload로 보낼거면 string을 집어넣으면 된다.
(신규방식 redux) state를 꺼낼 때
import { useDispatch, useSelector } from 'react-redux';
import { RootState, increment } from './index';
function App() {
const 꺼내온거 = useSelector((state: RootState) => state);
const dispatch = useDispatch();
return (
<div className='App'>
{꺼내온거.counter1.count}
<button
onClick={() => {
dispatch(increment());
}}
>
버튼
</button>
</div>
);
}
state를 꺼낼때 타입지정은 state와 dispatch에 해주면 된다.
(1) useSelector()안의 파라미터에 타입을지정해주면 된다.
state가 어떻게 생겼는지 파악한 다음 타입을 알아서 지정해주거나,
타입을 index.ts이런 리듀서 만든곳에서 미리 RootState
라는 타입을 export 해두면 위의 코드처럼 import해서 사용할 수 있다.
(2) useDispatch()사용할 때 타입지정이 가능하다.
예전처럼 Dispatch
라는 타입을 임폴트해서 사용하던가
공식문서에서 말하는것처럼,
index.ts에서 export type AppDispatch = typeof store.dispatch
해두고,
App.tsx에서 import 해와서 useDispatch
강사는 공식문서처럼안하고, Dispatch
라는 타입을 임폴트해서 사용한다고한다.