TypeScript

박상하·2023년 2월 14일
0

React

목록 보기
2/7
post-thumbnail

이전에 타입 스크립트를 조금 배웠었지만 그때는 이해가 잘 되지 않아 Skip(...노답) 했던 기억이 났기 때문에
이번 React 강의를 들으면서는 최대한 이해하며 끝까지 붙들어 메고 있었다.

역시 TS는 JS를 기반으로 한 프로그래밍 언어이다..
JS실력이 몇 달전보다 나아진 지금 TS를 이해하기에 더 쉬운 느낌이었다!!

시작과 동시에 오류를 만나다..

리액트에 타입스크립트를 적용하기위해 tsx 파일 확장자를 만드는 과정에서 오류가 발생하였다.

궁금증! .ts 확장자와 .tsx 확장자의 차이점이 궁금해 구글링한 결과
.ts 확장자는 JSX 문법 사용이 불가능한 only TS 파일이고
.tsx 확장자는 JSX 문법이 사용 가능한 TS 파일이다!

정확히는 styled-component를 적용하려는데 오류가 발생하였다.

오류의 내용은 다음과 같다.

왜 계속 Hook 이 잘못 사용되었다는 오류가 발생하는지 의문이었다.
Hook을 사용한적이 없는데 말이다..
일단 오류의 내용은 이렇다

  1. Hook 사용법이 잘못된거같다.
  2. React 와 React - Dom 의 버전이 옳지 않다.
  3. 같은 리액트 앱이 두개가 존재한다.

이를 보고 그나마 내가 잘못건드린 것은 버전이 잘못됐나보다하고
react,react-dom 버전을 동일하게 맞추고, styled-component의 버전을 낮추어 보았다.

styled-component를 낮춰볼 아이디어는 구글에서 찾았는데 제로초 님의 답변을 참고하였다.
제로초님의 해결법

그렇게 하자 styled-component가 오류를 발생시키지 않고 실행되었다.
그럼에도 왜 버전을 낮췄다고 이게 오류 발생을 막은건지 잘 납득이 되지 않았다.

다시 처음부터 깔고 지우고를 반복했다. 그렇게 하다보니 나의 바보같은 설치법에 문제가 있었음을
알게되었다..

설치방법

npx create-react-app 내 앱 이름 --template typescript
npm i --save-dev @types/styled-components
npm i styled-components

기본적으로 필자는 위 터미널 코드를 복사 붙여넣기하여 리액트와 타입스크립트와 styled-component를 세팅하였다.
그런데 위 코드를 상위 폴더에서 모두 실행시켰었다....
그러다 보니 styled-component가 정상적인 루트로 설치가 되지 않아서 발생했던 문제였다.

느낀점은 항상 무언가를 설치할 때 폴더의 위치를 잘 보고 설치해야겠다는 점이다ㅜ😅

그래도 이 오류를 만나서 Hook 을 사용할 때의 올바른 사용법, react와 react-dom의 버전이 일치하지 않았을 때 발생하는 오류, 버전에 따른 호환성등을 배울 수 있었다 !!

props에 타입 정해주기

기본적으로 리액트는 props를 계속해서 하위 컴포넌트에 보내고 또 상위 컴포넌트에서 받아오고
이 짓(?)을 잘해야 하는 거 같다. 그렇기 때문에 Props의 Type에 대한 정의 역시 중요하다.

필자는 props의 type 정의에 대한 설명을 해보겠다.

const App =()=>{
    return
  (
    <OneTitleComponent  text="One"/>
  <TwoBoxComponent text="Two" />
  )
}
// 이렇게 상위 컴포넌트에서 정보(props)를 보냈다면 

const OneTitleComponent =(props)=>{
 return <h1>
   {props.text}
   </h1> 
}

const TwoBoxComponent=(props)=>{
 return ( <div>
         ${props.text}
         </div>) 
}


// 이렇게 하위 컴포넌트에서 정보(props)를 사용할 수 있다. 이때,
// props에 대한 타입의 정의가 필요하다! 아래와 같이 정의해주면 된다.

정의 후


 interface OneTitleProps{
 text:string; 

}
 interface TwoBoxProps{
 text:string; 
}

const OneTitleComponent =(props: OneTitleProps)=>{
 return <h1>
   {props.text}
   </h1> 
}

const TwoBoxComponent=(props: TwoBoxProps)=>{
 return ( <div>
         ${props.text}
         </div>) 

위 코드에서 볼 수 있듯이 props에 대한 타입 설명은
interface 라는 Object를 설명해주는 장치를 이용해주면 된다!
props는 기본적으로 object이기 때문!!!!!!!

받아온 props, styled-component에 적용해주기

받아온 props를 다시 styled-component에서 사용하는 경우가 있다.
이렇게 하면 interface를 사용하여 다시 타입을 지정해주는 것은 같지만
적용하는 방법이 다르다고 필자는 느꼈다!

const App =()=>{
return 
  <Box bgColor="orange">
  </Box>  
  
}
//위 orange라는 정보를 받아옴

interface ContainerProps{
  bgColor:string;
}

interface BoxProps{
bgcolor:string;
}

//styled-component에서 props를 사용하면
//type을 아래와 같은 방식으로 정하면 된다!
const Container = styled.div<ContrainerProps>`
background-color=${(props)=>props.bgColor}

`
// 여기에서의 bgColor는
//받아온 props를 다시 Container라는 스타일화 된 컴포넌트에 보낸것

const Box = (props:BoxProps)=>{
 return 
  <Container bgColor=${props.bgcolor}>// {}안에있는 bgcolor는 App에서받아온것
   Hello!
   </Container> 
  
}

Props는 기본적으로 require 되게 설계되어있다!

코드를 짜면서 만약 동일한 Props를 특정 컴포넌트만 주고싶다면 어떻게 해야할까?
기본적으로 Props에 값을 넣고 type을 설정하면 interface는 해당 props는 필수적으로
들어가야한다고 설정이 된다.
즉 안 쓰이면 오류가 발생하는 것이다! 자세한 설명은 아래의 코드를 봐보겠다!

const App=()=>{
 return (  
  <One bgcolor="white"/>
   <Two/>
   )
}

interface boxProps {
  bgcolor:string;
  
}

const Box = styled.div`
background-color:${props=>props.bgcolor}

`
const One=({bgcolor}:boxProps)=>{
 return 
  <Box bgcolor=bgcolor></Box>
  <Box></Box>// <<<오류발생!!
  //이렇게하면 아래 Box에서 오류가 발생한다 왜냐하면 interface에서
  // 타입을 정리할 때 bgcolor가 사용되는것으로 정의가 됐기 때문이다!
}

위 코드와 같이 props는 당연히 사용될 것으로 데이터를 보내기 때문에
사용되지 않는다면 오류를 발생시킨다. 이를 막는 방법은
optional props이다! interface에서 타입을 정하여줄때

interface PropsTypes{
A: string
B?:string
}
이렇게 "?"를 붙이면 있어도 되고 없어도 되고라는 말이다!!

필수적인 props가 아니면 타입을 정하여 줄때 ?를 붙이면된다. 보통 styled-component에 사용되는 props가 optional props로 설정해야할 경우가 많아보인다.

props 기본값 설정

props의 기본값을 따로 설정할 수 있다. 위의 optional props를 설정하여 있어도 되고 없어도 된다면. 사용자는 props를 사용하지 않았을 때의 고정 데이터를 설정하고 싶을 수 있다. 그 방법은 아래의 코드와 같다.

function Circle({ bgColor, borderColor }: CircleProps) {
  const [count, setCount] = useState<number>(0);
  // State에 대한 type 설명할 때
  console.log(count);
  return (
    //함수에서 props를 사용할 때 props의 타입에 대한 설명이 필요
    <Container borderColor={borderColor ?? "black"} bgColor={bgColor}>
    </Container>

//위 ?? 를 보면 ?? 다음 기본 값을 설정해주면 props가 undefined(사용되지 않았을때)
// 그때의 값을 지정해줄 수 있다! 
  );
}

state의 Type

state는 리액트에서 아주유용한기능 중 하나이다.
위 state 역시 type을 정해주어야한다!

state는 기본적으로 사용자가 설정한 초기값에 타입을 맞춘다 예를들어

const [value,setValue] = useState(1)

이면 value의 type은 number

const [value,setValue] = useState("Hello")

이면 value의 type은 string

const [value,setValue] = useState(true)

이면 value의 type은 boolean 이 된다.

직접 타입을 정해줄 수 있는데 그 방법은

const [value,setValue] = useState<number|string>(12)

이렇게 설정이 가능하다!

TS 환경에서 Event 다루기

JS 환경과 TS 환경에서의 event를 다루는 방법은 각각 다르다.

먼저 JS 환경에서는 일반적으로 써오던 방식을 사용하면 된다.

const [value,setValue] = useState(1)
const onChange=(event)=>{
  setValue(event.target.value)
}

TS 환경에서는 먼저 state 타입에 대한 정의와 event의 타입에 대한 정의 역시 필요로한다.

const [value,setValue]=useState(1)
const onChange=(event:React.FormEvent<HTMLFormElement>)=>{
  setValue(event.currentTarget.value)
}

위 코드처럼 event에 대한 타입을 정해주어야 하는데 복잡해보이지만
복잡한게 맞다. 사실 니코쌤도 이건 그냥 받아들이는거라 설명해서 이부분은 그냥 사용하면서 더 익숙해져보려한다!

event의 기본 타입은 any로 정의 된다.

any의 타입은 최대한 지양하는 것이 좋다. any인 상태로 ts를 진행한다면 js를 진행하는 것과 동일하기 때문이다!!

Theme의 Type은 DefaultTheme에서

Theme은 모든 색을 가지고 있는 object라고 저번시간에 배웠다.
그 많은 object의 속성의 타입을 지정해줄 때 DefaultTheme이라는 inferface에서 관리한다.

즉, DefaultTheme은 기본적으로 props.theme의 인터페이스로 사용이 된다!
또한 DefaultTheme interface는 비어 있으므로 확장해야한다!

DefaultTheme 가져오는법

import "styled-components";

// and extend them!
declare module "styled-components" {
  export interface DefaultTheme {
    textColor: string;
    bgColor: string;
    btnColor: string;
  }
}

위 코드와 같이 theme에서 사용한 속성의 타입을 정의하고

import { DefaultTheme } from "styled-components";

export const ligthTheme: DefaultTheme = {
  bgColor: "white",
  textColor: "black",
  btnColor: "tomato",
};
export const darkTheme: DefaultTheme = {
  bgColor: "black",
  textColor: "white",
  btnColor: "teal",
};

위 처럼 DefaultTheme이 필요한 곳(타입 설명이 필요한 object)에 넣어주면 된다.
defaultTheme에서 optional 한 타입 설정이 많이 사용 될 거 같다!

오늘은 TS와 함께 리액트를 학습해보았다!! 이제 다음 포스팅은 React가 업데이트 된 후 바뀐
최신 문법을 배워 볼 것이고 그 후 클론 코딩을 시작해보겠다!!
화이🔥

0개의 댓글