React TypeScript (To-do App)

Harimad·2022년 12월 16일
1

React

목록 보기
12/18
post-thumbnail

Intro

  • React에서 TypeScript를 적용해서 Todo 앱을 만들어 보겠습니다.
  • 본론에서는 파일마다 코드가 바뀌는 스냅샷을 두었습니다.
  • 정리란에는 각 파일의 코드를 넣었으니 코드를 참고하면 좋습니다.

1. 본론

1-1. 할 일 추가하기

📄 src / App.tsx

📄 src / components / Todos.tsx

실행결과

📄 src / App.tsx

📄 src / components / Todos.tsx

  • 타입 지정

  • 🧐 React.FC<{ items: string[] }> ?
    • React.FC 는 아래와 같습니다.
    • < >안에 props의 타입 지정합니다.
    • { items: string[] } 👉 즉 item이 문자 배열 타입입니다.

실행결과

📄 src / utils / todos.ts

  • 클래스 구조

📄 src / App.tsx

📄 src / components / Todos.tsx

  • 배열 props

실행결과

1-2. 컴포넌트 분리하기

📄 src / components / Todos.tsx


📄 src / components / TodoItem.tsx

실행결과

1-3. 입력 기능 추가하기

📄 src / components / InsertTodo.tsx


실행결과

📄 src / components / InsertTodo.tsx

  • 이벤트



  • 텍스트 비우기

📄 src / App.tsx

  • 입력 컴포넌트 연결하기

📄 src / components / InsertTodo.tsx

  • props 타입 설정하기

📄 src / App.tsx

  • todos를 useState()로 관리하기

  • 할 일 추가 함수 구현하기

실행 결과

  • 할 일 추가 완료

1-4. 스타일 추가하기

src / components / Todos.tsx

  • Todos 스타일링

src / components / Todos.module.css

src / components / TodoItem.tsx

  • TodoItem 스타일링

src / components / TodoItem.module.css

src / components / TodoTodo.tsx

  • InsertTodo 스타일링

src / components / TodoTodo.module.css

스타일 추가 완료

1-5. 삭제 기능 추가하기

📄 src / App.tsx

📄 src / components / Todos.tsx

📄 src / components / TodoIetm.tsx

📄 src / App.tsx

2. 정리

2-1. 파일 구조

2-2. 각 파일 코드

🟡 App.tsx

import React, { useState } from 'react'
import Todos from './components/Todos'
import Todo from './utils/todo'
import InsertTodo from './components/InsertTodo'

const App = () => {
  const [todos, setTodos] = useState<Todo[]>([])
  const addTodoHandler = (item: string) => {
    const newTodo = new Todo(item)

    setTodos(prevTodo => {
      return [...prevTodo, newTodo]
    })
  }

  const removeTodoHandler = (id: string) => {
    setTodos(prevTodos => {
      return prevTodos.filter(todo => todo.id !== id)
    })
  }

  return (
    <div>
      <InsertTodo onAddTodo={addTodoHandler} />
      <Todos items={todos} onRemoveTodo={removeTodoHandler} />
    </div>
  )
}

export default App

🟠 todos.ts

class Todo {
  id: string
  text: string

  constructor(todoText: string) {
    this.id = String(new Date().getTime())
    // this.id = new Date().toLocaleString()
    this.text = todoText
  }
}

export default Todo

🔵 InertTodo.tsx

import React from 'react'
import { useState } from 'react'
import style from '../style/InserTodo.module.css'

const InsertTodo: React.FC<{ onAddTodo: (item: string) => void }> = props => {
  const [text, setText] = useState('')

  const submitHandler = (e: React.FormEvent) => {
    e.preventDefault()
    if (text.trim() !== '') {
      props.onAddTodo(text)
      setText('')
    }
  }

  const changeHandler = (e: React.FormEvent<HTMLInputElement>) => {
    setText(e.currentTarget.value)
  }

  return (
    <div>
      <form onSubmit={submitHandler} className={style.form}>
        <h3>할일 추가</h3>
        <input type="text" value={text || ''} onChange={changeHandler} />
        <button>추가</button>
      </form>
    </div>
  )
}

export default InsertTodo

🔵 InsertTodo.module.css

.form {
  width: 40rem;
  margin: 2rem auto;
}

.form input {
  width: 50%;
  font: inherit;
  font-size: 1.5rem;
  padding: 0.5rem;
  background-color: #fff;
  border: none;
  outline: none;
  border-bottom: 2px solid #f06292;
  margin-right: 1rem;
}

.form button {
  font: inherit;
  background-color: #f06292;
  border: none;
  color: #fff;
  padding: 0.5rem 1.5rem;
  border-radius: 4px;
  cursor: pointer;
}

🟢 Todos.tsx

import React from 'react'
import Todo from '../utils/todo'
import TodoItem from './TodoItem'
import style from '../style/Todos.module.css'

const Todos: React.FC<{
  items: Todo[]
  onRemoveTodo: (id: string) => void
}> = props => {
  return (
    <ul className={style.todos}>
      {props.items.map(item => (
        <TodoItem
          key={item.id}
          text={item.text}
          id={item.id}
          onRemoveTodo={props.onRemoveTodo}
        />
      ))}
    </ul>
  )
}

export default Todos

🟢 Todos.module.css

.todos {
  list-style: none;
  margin: 2rem auto;
  padding: 0;
  width: 40rem;
}

🟣 TodoItem.tsx

import React from 'react'
import style from '../style/TodoItem.module.css'

const TodoItem: React.FC<{
  text: string
  id: string
  onRemoveTodo: (id: string) => void
}> = props => {
  return (
    <li className={style.item} onClick={() => props.onRemoveTodo(props.id)}>
      {props.text}
    </li>
  )
}

export default TodoItem

🟣 TodoItem.module.css

.item {
  margin: 1rem 0;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  padding: 1rem;
  background-color: #ffcdd2;
}

나가면서

  • React에서 TypeScript를 적용하여 할일 앱을 만들어 보았습니다.
  • TypeScript를 쓰면서 많은 오류가 발생했습니다.
  • 이 오류들이 처음엔 번거로운 작업이라서 느껴졌습니다.
  • 하지만 오류를 세세하게 잡고나가니 코드가 점점 많아 질때는 오히려 디버깅이 쉬워졌습니다.
  • 타입스크립트의 필요성을 느끼게 되었습니다.
profile
Here and Now. 🧗‍♂️

0개의 댓글