React 환경에서 Redux에 typescript를 적용하는 방법이다.
(Redux toolkit)
React + javascript 환경에서 짜여진 Redux 코드에 typescript를 적용하는 과정을 보여주는 글로, redux 관련 세부 코멘트는 생략한다.
코드는 여기저기 구글링을 하며 짬뽕한 코드이다.
Redux로 상태관리를 하기 위한 최소한의 코드 & 기능 만을 포함한다.
(미들웨어 같은거 없다)
파일을 아래와 같이 생성 및 작성한다. (3개 파일)
Redux store, reducer 등을 관리하는 파일이다.
redux-roolkit을 사용했다 (createSlice, configureStore 등)
state는 title과 info(이름, 나이)이고 타입은 코드 안의 interface IState 와 같다.
// Store.ts
import { createSlice, PayloadAction, configureStore } from '@reduxjs/toolkit';
// state interface
export interface IState {
title: string;
info: IInfo;
}
export interface IInfo {
name: string;
age: number;
}
// createSlice
const documentSlice = createSlice({
// slice name 설정
name: 'document',
// 초기 state 설정
initialState: {
title: '초기 정보',
info: {
name: '김처음',
age: 1,
},
},
//reducer 설정
reducers: {
setTitle: (state, action: PayloadAction<string>) => {
state.title = action.payload;
},
setInfo: (state, action: PayloadAction<IInfo>) => {
state.info = action.payload;
},
},
});
// configureStore
const store = configureStore({ reducer: documentSlice.reducer });
// export actions
export const { setTitle, setInfo } = documentSlice.actions;
// export store to index.tsx
export default store;
react-redux의 provider로 App 컴포넌트를 감싸준다
// index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import store from './Reducers';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
react-connect를 사용하여 각 components에서 state를 참조하거나, action을 발생시켜(dispatch) state를 변경(reducer 함수 실행)할 수 있다.
typescript를 적용하는 방법 중 react-redux 공식문서에서 제안하는 방법은 connectedProps 를 사용하는 방법이다. (공식문서 / react-redux & typescript)
const mapStateToProps = (state: IState) => {
return {
// state
};
};
const mapDispatchToProps = (dispatch: any) => {
return {
// dispatch
};
};
const connector = connect(mapStateToProps, mapDispatchToProps);
// components 의 파라미터로 들어갈 type (from redux state)
type PropsFromRedux = ConnectedProps<typeof connector>;
export default connector(App);
위와 같이 connector라는 변수에 connect(mapStateToProps, mapDispatchToProps)를 할당하고,
이 변수와 connectedProps를 사용해서 type을 추출하고, 이를 해당 컴포넌트의 type으로 지정한다. (PropsFromRedux)
App.tsx의 전체 코드는 아래와 같다.
// app.tsx
import React, { useState } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { setTitle, setInfo, IInfo, IState } from './Reducers';
// 아래에서 정의한 type을 적용한다.
function App(props: PropsFromRedux) {
// redux 변화를 확인하기 위한 코드 (버튼을 누르면 redux state가 업데이트 되고, state가 렌더링된다.)
const [isTrue, setIsTrue] = useState(true);
const handleClick = () => {
if (isTrue) {
props.setTitle('진짜정보');
props.setInfo({
name: '김진짜',
age: 25,
});
setIsTrue(false);
} else {
props.setTitle('가짜정보');
props.setInfo({
name: '김가짜',
age: 2500000,
});
setIsTrue(true);
}
};
return (
<>
<div>
<h1>This is home component</h1>
<button onClick={handleClick}>btn</button>
<p>{props.title}</p>
<p>{props.info.name}</p>
<p>{props.info.age}</p>
</div>
</>
);
}
const mapStateToProps = (state: IState) => {
return {
title: state.title,
info: state.info,
};
};
const mapDispatchToProps = (dispatch: any) => {
return {
setTitle: (data: string) => dispatch(setTitle(data)),
setInfo: (data: IInfo) => dispatch(setInfo(data)),
};
};
// react-redux connect
const connector = connect(mapStateToProps, mapDispatchToProps);
// components 의 파라미터로 들어갈 type (from redux state)
type PropsFromRedux = ConnectedProps<typeof connector>;
export default connector(App);
타입스크립트와 함께라면 코드를 작성할 때 이렇게 편리하게 작성할 수 있다.
이제 state가 변경이 잘 되는지 확인해보자.
초기화면
btn 클릭!
btn 한 번 더 클릭!
state가 잘 바뀌는 것을 확인할 수 있다.
끝!