본문 바로가기
TYPESCRIPT

리액트와 타입스크립트

by 일태찡 2023. 4. 11.

 

Props로 작업하기

 

App.tsx

import React from "react";

import TodoList from "./components/TodoList";

           // 1
const App: React.FC = () => {
  const todos = [{ id: "t1", text: "타입스크립트 공부 마무리" }];
  
  return (
    <div className="App">
      <TodoList items={todos} /> // 2
    </div>
  );
};

export default App;

 

  1. 리액트에서 제공하는 Function Component 타입이고 JSX를 리턴합니다.
  2. TodoList 컴포넌트로 todos를 전달합니다.

 

TodoList.tsx

import React from "react";

// 1
interface TodoListProps {
    items: {id: string, text: string}[];
}

                         // 1
const TodoList: React.FC<TodoListProps> = props => {
  return (
    <ul>
      // 2
      {props.items.map((todo) => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
};

export default TodoList;

 

  1. 컴포넌트 안에서 프롭을 사용한다면 타입스크립트에게 이 프롭들이 어떻게 생겼고 어떤 구조를 갖고 있는지 알려줘야 한다는 것입니다. 따라서 인터페이스를 통해 프롭의 구조를 설명하고 제네릭 타입으로 컴포넌트에 알려줍니다.
  2. 프롭 배열의 수만큼 매핑하여 리스트를 나열합니다.

 

 

"ref"로 사용자 입력받기

 

NewTodo.tsx

import React, { useRef } from "react";

const NewTodo: React.FC = () => {
                             // 1
  const textInputRef = useRef<HTMLInputElement>(null);

  const todoSubmitHandler = (event: React.FormEvent) => {
    event.preventDefault();
    const enteredText = textInputRef.current!.value; // 2
  };

  return (
    <form onSubmit={todoSubmitHandler}>
      <div>
        <label htmlFor="todo-text">할 일 목록</label>
        <input type="text" id="todo-text" ref={textInputRef} />
      </div>
      <button type="submit">추가</button>
    </form>
  );
};

export default NewTodo;

 

  1. 이 ref안에 어떤 데이터가 저장될지 아는 것이 중요합니다. 지금은 input element이고 기본값은 null입니다.
  2. null일 수 있기에 느낌표(!)로 타입스크립트에게 이 값이 잘 설정될 것이라고 알립니다.

 

 

Cross-component 커뮤니케이션 & 상태 관리

 

todo.model.ts

export interface Todo {
    id: string;
    text: string;
}

 

App.tsx

import React, { useState } from "react";

import TodoList from "./components/TodoList";
import NewTodo from "./components/NewTodo";

import { Todo } from "./todo.model";

const App: React.FC = () => {
  const [todos, setTodos] = useState<Todo[]>([]); // 1

  const todoAddHandler = (text: string) => {
    // 2
    setTodos((prevTodos) => [
      ...prevTodos,
      { id: Math.random().toString(), text: text },
    ]);
  };

  return (
    <div className="App">
      <NewTodo onAddTodo={todoAddHandler} />
      <TodoList items={todos} />
    </div>
  );
};

export default App;

 

NewTodo.tsx

import React, { useRef } from "react";

// 3
type NewTodoProps = {
    onAddTodo: (todoText: string) => void;
}

                        // 3
const NewTodo: React.FC<NewTodoProps> = props => {
  const textInputRef = useRef<HTMLInputElement>(null);

  const todoSubmitHandler = (event: React.FormEvent) => {
    event.preventDefault();
    const enteredText = textInputRef.current!.value;
    props.onAddTodo(enteredText);
  };

  return (
    <form onSubmit={todoSubmitHandler}>
      <div>
        <label htmlFor="todo-text">할 일 목록</label>
        <input type="text" id="todo-text" ref={textInputRef} />
      </div>
      <button type="submit">추가</button>
    </form>
  );
};

export default NewTodo;

 

  1. useState를 이용하여 상태를 관리하고 초기값이 없기에 todos의 구조를 인터페이스로 정의하여 제네릭으로 연결합니다.
  2. 배열과 스프레드 문법으로만 구현하면 리액트 상태 업데이트 일정상 최신 상태가 아닐 수 도 있기에 함수에 함수를 전달해 상태를 업데이트해 최신 스냅샷을 보장받습니다.
  3. 프롭 함수의 구조를 타입으로 정의하고 제네릭으로 연결합니다.

'TYPESCRIPT' 카테고리의 다른 글

장소 선택 및 공유 구글 API 연습  (5) 2023.04.10
웹팩(Webpack) 사용하기  (6) 2023.04.07
모듈과 네임스페이스  (6) 2023.04.06
연습 프로젝트 4  (6) 2023.04.04
연습 프로젝트 3  (6) 2023.04.03