Typescript - 13(React)

hoin_lee·2023년 8월 4일
0

TypeScript

목록 보기
14/14

React에서의 Typescript

정말 현재 가장 많이 쓰는 React는 javascript 태생이기에 당연히 Typescript의 타입을 쓸 수 있다.

시작하기

공식문서에서 타입스크립트 추가부분을 본다면
npx create-react-app my-app --template typescript
라고 시작하는 부분을 확인할 수 있다. 여기서 --template typescript는 옵션 또는 플래그가 Create React 앱에게 Typescript 앱을 만든다고 알려주고 TypeScript를 포함하고 자동으로 tsconfig파일을 생성하도록 한다

이러면 .jsx파일 대신 .tsx파일을 생성한다

꼭 CRA를 사용할 필요는 없고 간단하다면 npm install @types/react를 실행해서 Typescript 타입을 추가해줘도 된다.

컴포넌트 작성

함수형 컴포넌트로 만들 예정이다

//Greeter.tsx
import React from "react"

function Greeter() {
  return <h1>Hello!</h1>
}

export default Greeter

이렇게 기본적인 컴포넌트를 하나 만들었는데 구문에 타입 애너테이션도 제네릭도 없고 그냥 일반적으로 작성된 것과 같아보인다
하지만 여기서도 타입이 생성된다. 함수의 추론된 반환 타입을 보면 JSX.Element이다
react 타입 정의나 react-dom 타입 정의를 사용할 때 얻는 타입 정의이다
CRA를 설치할 때 같이 설치된 것으로 Go to Type Definition으로 따라가면 정의를 볼 수 있다

실수를 방지하기 위해 애너테이션을 추가할 수 있는데

//Greeter.tsx
import React from "react"

function Greeter():JSX.Element {
  return <h1>Hello!</h1>
}

export default Greeter

이처럼 직접 애너테이션을 추가해주면 된다

그럼 React.FC라고 있던데 이건 뭘까?
React.FC = Function Component의 줄임말로 이는 React 타입의 일부이다. 이전 React강의에서 typescript를 함께 섞어 배울 때 React.FC를 이용했지만 사용하지 않는 게 좋은 것 같아 사용하지 않았었다(실제로 사용하지 않는게 좋다는 글도 많았고 말이다)
사용방법은

//Greeter.tsx
import React from "react"

const Greeter:React.FC = () => {
  return <h1>Hello!</h1>
}

export default Greeter

프로퍼티 다루기

위에 만들었던 Greeter 컴포넌트를 통해 각기 다른 값을 전달해보려고 한다

// App.tsx

function App(){
  return (
    <div className="App">
    	<Greeter person="Colt" />
    	<Greeter person="Blue" />
    </div>
  )
}

그러면 일단 person쪽에서 에러가 발생하는데 intrinsicAttributes타입을 할당할 수 없고 person 프로퍼티는 intrinsicAttributes 타입에 존재하지 않는다고 한다
Greeter컴포넌트가 person을 파라미터로 받게 해주면 된다

import React from "react"

function Greeter(props:{person:string}):JSX.Element {
  return <h1>Hello!,{props.person}</h1>
}

export default Greeter

이러면 서로 연결시켰다. 만약 받아야하는 데이터 값이 많아질 경우 어떻게 할까?

import React from "react"

interface GreeterProps = {
  person: string
}

function Greeter({person}:GreeterProps):JSX.Element {
  return <h1>Hello!,{person}</h1>
}

export default Greeter

구조분해 할당을 통해 {person}으로 분해햇고 interface를 만들어 해당 타입을 바로 애너테이션으로 집어 넣었다
이렇게 간단히도 가능하다

useState,useRef-typescript

useState

useState를 사용할 때 타입은 어떻게 사용해야 할까?
타입을 확인해보면 function useState<S>(initalState:S|(()=>S):[S,Dispatch<SetStateAction<S>>]길게 타입이 적혀 있는 부분을 확인 할 수 잇는데

일단 initalState를 제공하자. 어차피 우리가 썼던것처럼 해보면
const [item, setItem] = useState([])
이렇게 적는데 문제가 있다.
item을 확인해보면 items: neverp[]라고 타입이 생겼다.
[]를 작성했기 때문에 기본적으로 빈 배열 리터럴 타입으로 설정되는데 우리가 원하는 형태는 아니다

interface Item {
  id: number;
  product: string;
  quantity: number;
}

const [item, setItem] = useState<Item[]>([])

이런식으로 객체 interface로 타입을 만들고 useState뒤에 홑화살 구문으로 제네릭 타입을 넣어주면 빈 배열값을 가지지만 item은 해당 제네릭 배열의 타입을 갖도록 만들 수 있다

useRef

cheatsheet를 살펴보면
useRef도 useState처럼 제네릭 타입을 가지고 있기에 타입을 전달해야한다

요소(Element)타입만 인수로 제공하며 초기값으로 null을 사용하기도 한다라 나와있다

const inputRef = useRef<HTMLInputElement>(null);
console.log(inputRef.current?.value);

이처럼 만들면 된다
inputRef.current?.value여기서 ?를 사용했는데 null일수도 있으니 사용한 것으로 !를 사용해서 null이 아니라고 확신시켜도 가능하다

마지막

react에서 작성시 중요한 차이점으로
1. 코드를 tsx파일에 작성한다
2. 코드 작성시 모든 걸 타입 지정해준다. 특히 프로퍼티를 다룰 때(함수마다 어떤 시그니처와 어떤 프로퍼티 타입이 전달되는지 작성)
보통 interface를 많이 사용하고 타입 별칭도 물론 쓰지만 같은 파일이나 인라인에서만 사용하는 게 일반적이다.

profile
https://mo-i-programmers.tistory.com/

0개의 댓글