react + redux + typescript를 이용한 프로젝트 생성을 알아보려 한다
타입스크립트가 적용되는 reaxt + nextjs 를 설치한다.
npx create-next-app --example with-typescript test-app
npx 를 사용하는 이유는 이전 포스팅을 참조하면 좋겠다.
redux, redux toolkit, immer 등 추가 설치한다
npm i redux react-redux immer @types/react-redux typesafe-actions
생성된 폴더로 이동하여 서버를 실행한다.
cd test-app
npm run dev
다음 로그가 뜨면 서버실행에 성공한 것이다.
localhost:3000 으로 접속가능하다
> with-typescript@1.0.0 dev /Users/dgpark/git/side-project/test-app
> next
ready - started server on http://localhost:3000
event - compiled successfully
event - build page: /
wait - compiling...
event - compiled successfully
localhost:3000 화면 모습
타입스크립트가 있는지 즉시 확인 가능하다,
파일을 열어 설정내용을 한번 보는걸 추천
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "preserve",
"lib": ["dom", "es2017"],
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "esnext"
},
"exclude": ["node_modules"],
"include": ["**/*.ts", "**/*.tsx"]
}
# Reducer 등록
이제 파일을 총 4개 생성한다
1) reducer 파일
2) reducer 설정 파일
3) store 생성 파일
2) _app.tsx 파일
Reducer 파일 생성 => 설정에 등록 => Store 생성 => _app.js 에 등록하는 과정이다
reducers 폴더를 만든 후, testReducer.ts 파일을 생성한다.
간단한 기능이 있는 Reducer를 하나 등록한다.
리듀서 등록 방법을 모른다면 이전글을 참조하면 도움이 된다.
testReducer.ts 파일 생성 및 아래코드를 넣는다
import {
createAction
, ActionType
, createReducer
} from 'typesafe-actions';
// 상태의 타입 선언
interface TestReducer {
no: number;
text: string;
}
// 상태 초기화
const initialState: TestReducer = {
no: 0,
text: "hello"
}
// 액션타입 선언
export const RESET_TEXT = "testReducer/RESET_TEXT";
export const ADD_TEXT = "testReducer/ADD_TEXT";
export const REMOVE_TEXT = "testReducer/REMOVE_TEXT";
// 액션함수 선언
export const resetText = createAction(RESET_TEXT)();
export const addText = createAction(ADD_TEXT)<TestReducer>()
export const removeText = createAction(REMOVE_TEXT)()
// 액션 객체타입
export const actions = {resetText, addText, removeText}
type TestReducerActions = ActionType<typeof actions>;
// 리듀서 추가
const testReducer = createReducer<TestReducer, TestReducerActions>(initialState, {
[RESET_TEXT]: () => ({
no: 0,
text: ""
}),
[ADD_TEXT]: (state, action) => {
console.log(state.text)
return ({
no: action.payload.no,
text: action.payload.text
})
},
[REMOVE_TEXT]: (state) => ({
no: state.no,
text: ""
})
})
export default testReducer;
Reducer를 설정파일에 등록한다
같은 폴더 내 index.ts 파일을 만든다
import { combineReducers } from "redux";
import testReducer from "./testReducer";
const rootReducer = combineReducers({
testReducer
})
export default rootReducer;
export type RootState = ReturnType<typeof rootReducer>;
store를 생성할 파일을 추가한다. 혹은 _app.tsx 내에 코드를 넣어놔도 상관없지만 여기선 설정을 분리했다.
configureStore.ts 생성
import { compose, createStore, Store } from "redux";
import rootReducer from ".";
declare global {
interface Window {
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
}
}
// store 생성
export default function configureStore():Store {
const composeEnhancers = typeof (window as any) !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
composeEnhancers()
);
return store;
}
설정한 것중에 __REDUX_DEVTOOLS_EXTENSION_COMPOSE__ 은 크롬에서 테스트할때 Redux 확장프로그램을 활용하기 위해 넣은 것이다. 사용하지 않는다면 createStore(rootReducer) 로만 생성해도 된다.
추후 운영, 개발서버 분리해서 띄우는 설정도 필요할텐데, 그건 추후에 포스팅 하는 것으로.
그럼 이제 생성한 파일들을 _app.tsx 파일에 등록해야 한다. 다음 파일을 생성한다.
import React from 'react'
import App, { AppContext, AppProps } from 'next/app'
import { Provider } from 'react-redux'
import configureStore from '../reducers/configureStore'
// store 설정파일 로드
const store = configureStore()
const TestApp = ({Component, pageProps}: AppProps) => {
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
)
}
TestApp.getInitialProps = async (appContext: AppContext) => {
const appProps = await App.getInitialProps(appContext);
return {...appProps}
}
export default TestApp
이제 설정이 끝났다.
test 컴포넌트를 만들어서 잘 작동하는지 확인해보자
pages 폴더 아래 test.tsx 파일을 생성한다
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../reducers";
import { actions, RESET_TEXT } from "../reducers/testReducer";
const Test = () => {
const {no, text} = useSelector((state: RootState) => state.testReducer)
const dispatch = useDispatch()
useEffect(() => {
dispatch({
type: RESET_TEXT
})
}, [])
const addTextHandler = () => {
const value = "world"
dispatch(actions.addText({no: 10, text: value}))
}
return (
<>
<p>no: {no}</p>
<p>text: {text || ""}</p>
<div>
<button onClick={addTextHandler}>
버튼
</button>
</div>
</>
)
}
export default Test;
localhost:3000/test 으로 접속해서 화면을 확인해보자.
버튼을 누르면 Reducer가 제대로 동작하는 것을 확인할 수 있다.
여기까지가 설정 완료다. 이제 프로젝트 내에 불필요한 파일을 정리하자.
pages/index.tsx 파일 정리
import Link from "next/link";
const IndexPage = () => (
<>
<p>React 시작하기</p>
<Link href="/test">
<a>Reducer Test 페이지 이동</a>
</Link>
</>
)
export default IndexPage
다음과 같이 화면이 뜬다
폴더 삭제: pages/users , pages/api
파일 삭제: about.tsx
최종 구성은 다음과 같다
끝.
해당 설정은 Github에 올렸습니다.
github.com/lemontia/react-redux-sample
'공부 > 프로그래밍' 카테고리의 다른 글
[airflow] BigQueryOperator 사용할때 location 에러 (0) | 2021.01.04 |
---|---|
[aws ec2] jenkins에 root 권한 주기 (0) | 2021.01.02 |
[npm] npm 대신 npx 를 사용하는 이유 (0) | 2020.12.24 |
[react + typescript] redux toolkit 사용하기(createAction , ActionType , createReducer) (0) | 2020.12.23 |
[querydsl] group by 쿼리만들기 (0) | 2020.12.18 |
댓글