본문 바로가기

Today I Learned (TIL)

23.12.18 리액트 타입스크립트 todolist

728x90
반응형

개인 과제로 타입스크립트 를 사용한 리액트 todolist를 만들어보았다

타입스크립트로 리액트에서 todolist 만들어 보는중

 

시작은 yarn create react-app (이름은 아무거나) --template typescript

 

useState 사용후 제네릭을 이용해 타입 지정

맵으로 뿌려주는데 불리언 타입은 적용이 안되서 toString 으로 해결

key값을 부여하는데 number는 들어갈수가 없다고 합니다

스트링 타입을 부여해서 해결

 

<div>
          <h1>할일 목록</h1>
          <ul>
            {todos
              .filter((todo) => todo.isDone === false)
              .map((todo) => (
                <div
                  key={String(todo.id)}
                  style={{
                    border: "1px solid black",
                    margin: "20px",
                  }}
                >
                  <h3>{todo.title}</h3>
                  <p> {todo.contents}</p>
                  <p> 완료 여부 : {todo.isDone.toString()}</p>
                </div>
              ))}
          </ul>
        </div>
 

필터를 이용해 할일 완료 미완료도 구분지어 준다

 

 

타입 오류가 뜬다

 

<form
            onSubmit={(event) => {
              event.preventDefault();
              const newTodo = {
                id: 1,
                title: title,
                contents: contents,
                isDone: false,
              };
              setTodos([...todos, newTodo]);
            }}
          >
            제목
            <input
              value={title}
              onChange={(event) => {
                setTitle(event.target.value);
              }}
            />
            내용
            <input
              value={contents}
              onChange={(event) => {
                setContents(event.target.value);
              }}
            />
            <button>입력 </button>
          </form>
 

대괄호 안에 안넣어 줘서 생기는 오류였습니다,일반 리액트였다면 뜨지않았을 오류인데

타입스크립트라서 실행전에 미리 잡아줬습니다

정상적으로 잘 입력되니 이제

삭제와 완료 버튼까지 만들어 봐야겠습니다

삭제버튼을 만들기위해 고유값은 uuid 를 yarn add react-uuid 통해 받은후 사용해봅니다

 

<h3>{todo.title}</h3>
                  <p> {todo.contents}</p>
                  <p> 완료 여부 : {todo.isDone.toString()}</p>
                  <button>완료</button>
                  <button
                    onClick={() => {
                      const deletedTodos = todos.filter((item) => {
                        return item.id !== todo.id;
                      });
                      setTodos(deletedTodos);
 

삭제 버튼 생성

완료 버튼 생성 고유 아이디 값이 동일하면 isDone을 반전시키는 코드를 사용했다

타입스크립트 사용한 todolist 완성이다

import React, { useState } from "react";
import uuid from "react-uuid";

function App() {
  type Todos = {
    id: string;
    title: string;
    contents: string;
    isDone: Boolean;
  };
  const [title, setTitle] = useState<string>("");
  const [contents, setContents] = useState<string>("");
  const [todos, setTodos] = useState<Todos[]>([
    {
      id: uuid(),
      title: "타입 스크립트 ",
      contents: "제네릭 연습하기 ",
      isDone: false,
    },
    {
      id: uuid(),
      title: "타입스크립트 과제",
      contents: "타입스크립트에 접목해서 todolist 만들기",
      isDone: true,
    },
  ]);

  return (
    <div>
      <header>
        <h1>Type Script TodoList </h1>
      </header>
      <main style={{ backgroundColor: "#fcf6bd" }}>
        <div>
          <form
            onSubmit={(event) => {
              event.preventDefault();
              const newTodo = {
                id: uuid(),
                title: title,
                contents: contents,
                isDone: false,
              };
              setTodos([...todos, newTodo]);
            }}
          >
            제목
            <input
              value={title}
              onChange={(event) => {
                setTitle(event.target.value);
              }}
            />
            내용
            <input
              value={contents}
              onChange={(event) => {
                setContents(event.target.value);
              }}
            />
            <button>입력 </button>
          </form>
        </div>
        <div>
          <h1>할일 목록</h1>
          <ul>
            {todos
              .filter((todo) => todo.isDone === false)
              .map((todo) => (
                <div
                  key={String(todo.id)}
                  style={{
                    border: "1px solid black",
                    margin: "20px",
                  }}
                >
                  <h3>{todo.title}</h3>
                  <p> {todo.contents}</p>
                  <p> 완료 여부 : {todo.isDone.toString()}</p>
                  <button
                    onClick={() => {
                      const newTodos = todos.map((item) => {
                        if (item.id === todo.id) {
                          return {
                            ...item,
                            isDone: !item.isDone,
                          };
                        } else {
                          return item;
                        }
                      });
                      setTodos(newTodos);
                    }}
                  >
                    완료
                  </button>
                  <button
                    onClick={() => {
                      const deletedTodos = todos.filter((item) => {
                        return item.id !== todo.id;
                      });
                      setTodos(deletedTodos);
                    }}
                  >
                    삭제
                  </button>
                </div>
              ))}
          </ul>
        </div>

        <div>
          <h1>완료된 목록</h1>
          <ul>
            {todos
              .filter((todo) => todo.isDone === true)
              .map((todo) => (
                <div
                  key={String(todo.id)}
                  style={{
                    border: "1px solid black",
                    margin: "20px",
                  }}
                >
                  <h3>{todo.title}</h3>
                  <p> {todo.contents}</p>
                  <p> 완료 여부 : {todo.isDone.toString()}</p>
                  <button
                    onClick={() => {
                      const newTodos = todos.map((item) => {
                        if (item.id === todo.id) {
                          return {
                            ...item,
                            isDone: !item.isDone,
                          };
                        } else {
                          return item;
                        }
                      });
                      setTodos(newTodos);
                    }}
                  >
                    완료취소
                  </button>
                  <button
                    onClick={() => {
                      const deletedTodos = todos.filter((item) => {
                        return item.id !== todo.id;
                      });
                      setTodos(deletedTodos);
                    }}
                  >
                    삭제
                  </button>
                </div>
              ))}
          </ul>
        </div>
      </main>
    </div>
  );
}

export default App;
 
 

 

 

생각보다 타입스크립트 적용이 간단한 편이였고 대괄호 생략했을때 오류를 바로 잡아줘서

규모가 큰 프로젝트라면 확실히 일반 JS보다는 편할거같다 익숙해지면 오히려 타입스크립트를 더 애용할지도

728x90
반응형

'Today I Learned (TIL)' 카테고리의 다른 글

TIL 23.12.20 [udemy] React 완벽 가이드 with Redux, Next.js, TypeScript  (1) 2023.12.20
Next.js 기초 23.12.19  (1) 2023.12.19
23.12.17 TIL  (0) 2023.12.17
23.12.16 TIL  (0) 2023.12.16
React Query 개념 정리 23.12.15  (0) 2023.12.15