나의 개발일지

[TypeScript] TodoList 만들기 (1) - props children 본문

TypeScript

[TypeScript] TodoList 만들기 (1) - props children

heew0n 2023. 12. 15. 14:31
// 명시적으로 타입을 지정해주지 않으면 오류 발생 
function Todos(props : {items : string[]}) {
    return (
    <ul>
      <li>Learn React</li>
      <li>Learn TypeScript</li>
   </ul>
  )
}

 

 

 

리액트에서 props는 언제나 객체 형태이다
정리하자면 props는 객체고, items를 키로 가지며, 문자열 배열을 값으로 갖는다는 것
이런 식으로 매번 지정하는 것은 번거롭다 그래서 제네릭 타입을 이용한다!

 

 

 

import React from "react";
// React.FC ==> 이 함수가 함수형 컴포넌트로 동작한다는 걸 명확히 하는 것
// FC 자체가 제네릭 타입이다 <> 안에는 우리가 만든 객체를 집어넣는다
const Todos: React.FC<{items: string[]}> = (props) => {  
    return (<ul>
{props.items.map(item => <li key={item}>{item}</li>)}
    </ul>
    );
}

export default Todos;

 

 

 

 

 


 

 

src > Todo.ts

 

 

 

 

 

이렇게만 쓰면 오류가 난다

이유는 text(id) 프로퍼티를 초기화하는 부분이 없고 생성자에서 값이 할당되지 않아서!

 

정의된 클래스 인스턴스화가 되어야 한다

그게 클래스를 사용하는 주된 목적이기 때문!

 

 

 

 

class Todo {
  id: string;
  text: string;

  constructor(todoText: string) {
    this.text = todoText;
    this.id = new Date().toISOString();
  }
}

export default Todo;

 

 

 

생성자를 만들어 값을 할당해준다

클래스 이름 'Todo'는 생성자 역할 뿐만 아니라 타입 역할도 한다

클래스 이름이 곧 타입이다

 

 

 

 

 

 

src > components > Todos.tsx 

 

import React from "react";
import Todo from '../models/todo'
// React.FC ==> 이 함수가 함수형 컴포넌트로 동작한다는 걸 명확히 하는 것
// FC 자체가 제네릭 타입이다 <> 안에는 우리가 만든 객체를 집어넣는다
// Todo 는 클래스 
const Todos: React.FC<{ items: Todo[] }> = (props) => {
  return (
    <ul>
      {props.items.map((item) => (
        <li key={item.id}>{item.text}</li>
      ))}
    </ul>
  );
};

export default Todos;

todo를 import 해주고

 { items: spring[ ] } 대신  { items: Todo[ ] } Todo 배열 클래스 넣기

 

map의 key 값과 item.text 바꿔주기

-->  Todo 배열에 text와 id가 있음

 

 


 

 

src > components > TodoItem.tsx

 

 

 

 

props에 타입을 지정해주지 않아서 오류 발생

 

import React from "react";
// text : Todo 를 가져올 수도 있음
const TodoItem: React.FC<{ text: string }> = (props) => {
  return (
    <div>
      <li>{props.text}</li>
    </div>
  );
};

export default TodoItem;

 

 

 

 

 

src > components > Todos.tsx 

 

import React from "react";
import Todo from "../models/todo";
import TodoItem from "./TodoItem";
// React.FC ==> 이 함수가 함수형 컴포넌트로 동작한다는 걸 명확히 하는 것
// FC 자체가 제네릭 타입이다 <> 안에는 우리가 만든 객체를 집어넣는다
// Todo로 바꾼다
const Todos: React.FC<{ items: Todo[] }> = (props) => {
  return (
    <ul>
      {props.items.map((item) => (
        <TodoItem key={item.id} text={item.text} />
      ))}
    </ul>
  );
};

export default Todos;

 

 


 

 

src > components > newTodos.tsx 

 

import React, { useRef } from "react";

const NewTodo: React.FC<{ onAddTodo: (text: string) => void }> = (props) => {
  // 반환 값이 필요 없다
  const todoTextInputRef = useRef<HTMLInputElement>(null);

  const submitHandler = (event: React.FormEvent) => {
    event.preventDefault();

    // ? --> 타입스크립트에 접근이 가능하면 그때 값을 가지고 온다는 것..
    // 접근이 불가능 하다면 null 값이 나올 것임
    // ! -->  null 값이 나올 거라는 걸 알지만, 이 시점에서는 절대 null 값이 아니라고 알려줌 : 100퍼 확신할 때
    const enteredText = todoTextInputRef.current!.value;

    if (enteredText.trim().length === 0) {
      // throw an error
      return;
    }

    props.onAddTodo(enteredText);
  };

  return (
    <form onSubmit={submitHandler}>
      <label htmlFor="text">TodoText</label>
      <input type="text" id="text" ref={todoTextInputRef} />
      <button>Add Todo</button>
    </form>
  );
};

export default NewTodo;