[Redux,TypeScript]_Counter

hanseungjune·2023년 3월 7일
0

비전공자의 IT준비

목록 보기
55/68
post-thumbnail

📌 화면 결과

📌 코드

// Counter.tsx
import styled from 'styled-components';
import { connect } from 'react-redux';

// Action 타입 정의
enum ActionType {
  Increment = 'INCREMENT',
  Decrement = 'DECREMENT'
}

// Action 객체 정의
interface IncrementAction {
  type: ActionType.Increment;
}

interface DecrementAction {
  type: ActionType.Decrement;
}

// Action 타입을 하나로 묶음
type Action = IncrementAction | DecrementAction;

// Increment Action 생성 함수
const Increment = (): IncrementAction => {
  return { type: ActionType.Increment };
}

// Decrement Action 생성 함수
const Decrement = (): DecrementAction => {
  return { type: ActionType.Decrement };
}

// 상태 타입 정의
interface State {
  count: number;
}

// 초기 상태값 정의
const initialState: State = {
  count: 0
};

// 리듀서 함수 정의
export const reducer = (state = initialState, action: Action): State => {
  switch (action.type) {
    case ActionType.Increment:
      return { ...state, count: state.count + 1}
    case ActionType.Decrement:
      return { ...state, count: state.count - 1}
    default:
      return state;
  }
}

// 스토어에서 사용할 mapStateToProps 함수 정의
const mapStateToProps = (state: State) => {
  return {
    count: state.count,
  }
}

// 스토어에서 사용할 mapDispatchToProps 함수 정의
const mapDispatchProps = {
  Increment,
  Decrement,
}

// 스타일드 컴포넌트 정의
const Container = styled.div`
  display: flex;
  align-items: center;
`;

const Button = styled.button`
  margin: 0 10px;
`

const Circle = styled.div<{count: number}>`
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background-color: ${({ count }) => ( count % 2 === 0 ? 'blue' : 'red')};
  color: white;
  font-size: 24px;
  font-weight: bold;
  display: flex;
  justify-content: center;
  align-items: center;
`

// 컴포넌트에서 사용할 props 타입 정의
interface Props {
  count: number;
  Increment: typeof Increment;
  Decrement: typeof Decrement;
}

// 컴포넌트 정의
function Counter({count, Increment, Decrement}: Props) {
  
  // 증가 버튼 클릭 핸들러
  const handleIncrement = () => {
    Increment();
  };

  // 감소 버튼 클릭 핸들러
  const handleDecrement = () => {
    Decrement();
  };

  return (
    <Container>
      <Button onClick={handleIncrement}>+</Button>
      <Circle count={count}>{count}</Circle>
      <Button onClick={handleDecrement}>-</Button>
    </Container>
  ); 
}

// connect 함수를 이용하여 컴포넌트와 스토어 연결
export default connect(mapStateToProps, mapDispatchProps)(Counter);
//App.tsx
import Counter from './components/Counter';

function App() {
  return (
    <div>
      <Counter />
    </div>
  ); 
}

export default App;
//index.tsx
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { reducer } from './components/Counter'; 

const store = createStore(reducer);

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);
{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.5.2",
    "@types/node": "^16.18.14",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@types/react-redux": "^7.1.25",
    "@types/redux": "^3.6.0",
    "@types/styled-components": "^5.1.26",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^8.0.5",
    "react-scripts": "5.0.1",
    "styled-components": "^5.3.8",
    "typescript": "^4.9.5",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

별 것도 없는게 코드가 엄청 길다... 프로젝트 할때 폴더 구조를 잘 짜야할 것 같다.

profile
필요하다면 공부하는 개발자, 한승준

0개의 댓글