한 걸음씩

TypeScript props, state, forms, themes 본문

React

TypeScript props, state, forms, themes

winter17 2023. 8. 1. 22:25

1. Props

 

▷ Props

  • PropTypes는 prop의 존재 여부를 알려주긴 하지만 코드가 실행된 이후에 알 수 있다
  • 반면에, 타입스크립트는 코드가 실행되기 전에 오류를 확인할 수 있다

▷ Optional Props

  • 타입스크립트에서 컴포넌트의 속성 중 일부가 반드시 필요하지 않을 때 사용하는 기능
  • 일부 속성이 있을 수도 있고 없을 수도 있으며, 필요에 따라 전달할 수 있는 속성

▷ interface

  • object shape(객체모양)을 타입스크립트에게 설명해 주는 타입스크립트의 개념
  • object가 어떤식으로 보일지 설명해 주는 것

 

// App.tsx
import Circle from './Circle'

function App() {
  return (
    <div>
      <Circle borderColor="black" bgColor="teal" />
      <Circle text="im here" bgColor="tomato" />
    </div>
  )
}

export default App

 

// Circle.tsx
import styled from 'styled-components'

// Container(스타일 컴포넌트)의 타입
interface ContainerProps {
  bgColor: string
  borderColor: string
}
// Circle 컴포넌트가 받은 props의 타입
interface CircleProps {
  bgColor: string // required
  borderColor?: string // optional
  text?: string // optional prop
}

const Container = styled.div<ContainerProps>`
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  width: 200px;
  height: 200px;
  background-color: ${props => props.bgColor};
  border-radius: 50%;
  border: 5px solid ${props => props.borderColor};
`

// Circle 컴포넌트는 bgColor를 받아 Container에 보냄
function Circle({ bgColor, borderColor, text = 'default text' }: CircleProps) {
  // props에 기본값 설정하기: text로 전달받은 텍스트가 없는 경우 'default text'을 기본값으로 표시
  return (
    <Container bgColor={bgColor} borderColor={borderColor ?? bgColor}>
      {/* borderColor가 있다면 borderColor사용하고, 아니라면 bgColor사용하기 */}
      {text}
    </Container>
  )
}
export default Circle

 

※ Nullish Coalescing 연산자

  • 자바스크립트에서 null 또는 undefined인 경우에만 우측의 값으로 대체하는 연산자
  • 'borderColor ?? bgColor'에서 borderColor가 null 또는 undefined인 경우 bgColor의 값으로 대체하고, 아니라면 borderColor의 값 그대로 사용한다

2. State 

  •  타입스크립트는 useState의 default값에 따라 어떤 타입을 쓸 건지 알고 있다
const [counter, setCounter] = useState(0)
const [counter, setCounter] = useState<number>(0)

const [counter, setCounter] = useState('hello')
const [counter, setCounter] = useState<string>('hello')

const [counter, setCounter]= useState(true)
const [counter, setCounter]= useState<boolean>(true)

 


3. Forms

 

// App.tsx
import React, { useState } from 'react'

function App() {
  const [value, setValue] = useState('')
  // React.js에서 타입을 모른다면 구글링!
  // 타입스크립트는 이 onchange 함수가 InputElement에 의해서 실행될 것을 알고 있다
  const onChange = (event: React.FormEvent<HTMLInputElement>) => {
    // React.js에서는 currentTarget사용. target과 동일함
    // 구조 분해 할당 사용
    const {
      currentTarget: { value },
    } = event
    setValue(value)
  }
  const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault()
    console.log('hello', value)
  }
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          value={value}
          onChange={onChange}
          type="text"
          placeholder="username"
        />
        <button>Log in</button>
      </form>
    </div>
  )
}

export default App
  • 타입스크립트를 사용하여 각 이벤트의 타입을 명시하면 코드의 안정성을 높이고, 잘못된 타입 사용으로 인한 오류를 사전에 방지할 수 있다
  • https://legacy.reactjs.org/docs/events.html

4. Themes

파일 구조
[왼] theme={darkTheme}.  [오] theme={lightTheme} 

▷ styled.d.ts

  • styled.d.ts 파일은 타입스크립트에서 외부 라이브러리 또는 모듈에 대해 타입을 지정할 때 사용하는 파일
  • styled-components 라이브러리의 타입을 확장하여 사용자 정의 테마를 지정
// styled.d.ts
import 'styled-components'

// styled-components 모듈에 대한 타입을 정의하겠다는 의미
declare module 'styled-components' {
  // DefaultTheme 인터페이스는 styled-components 라이브러리에서 기본적으로 제공하는 테마를 나타내는 인터페이스
  // DefaultTheme 인터페이스 확장하여 사용자 정의 테마를 지정하는 부분
  export interface DefaultTheme {
    textColor: string
    bgColor: string
  }
}

 

index.tsx

  • ThemeProvider는 styled-components 라이브러리에서 제공하는 컴포넌트로 전역적으로 테마를 적용할 때 사용된다
  • ThemeProvider는 'theme' props를 통해 테마 객체를 전달받는다.(App.tsx)
  • 이 테마 객체는 DefaultTheme 인터페이스를 따르는 객체여야 한다(theme.ts)
import React from 'react'
import ReactDOM from 'react-dom/client'
import { ThemeProvider } from 'styled-components'
import App from './App'
import { darkTheme, lightTheme } from './theme'

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)

root.render(
  <React.StrictMode>
    <ThemeProvider theme={lightTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>
)

 

▷ theme.ts

  • .ts는 타입스크립트만을 포함한 확장자
  • 아래의 theme.ts에서 lightTheme과 darkTheme객체를 styled-components 라이브러리의 DefaultTheme 인터페이스를 따르는 방식으로 정의하고, 해당 객체들을 export 하고 있다
  • lightTheme, darkTheme 객체들은 styled-components의 ThemeProvider를 사용하여 전역적으로 테마를 적용할 수 있다
import { DefaultTheme } from 'styled-components'

export const lightTheme: DefaultTheme = {
  bgColor: 'white',
  textColor: 'black',
  btnColor: 'tomato',
}
export const darkTheme: DefaultTheme = {
  bgColor: 'black',
  textColor: 'white',
  btnColor: 'teal',
}

 

▷ App.tsx

  • .tsx는 JSX 문법을 사용하는 React + TypeScript 코드를 사용하는 확장자를 말한다
import React, { useState } from 'react'
import styled from 'styled-components'

// index.tsx의 ThemeProvider 컴포넌트에서 'theme' props를 사용하여 테마 지정
const Container = styled.div`
  background-color: ${props => props.theme.bgColor};
`

const H1 = styled.h1`
  color: ${props => props.theme.textColor};
`

function App() {
  return (
    <Container>
      <H1>protected</H1>
    </Container>
  )
}

export default App

 

 

'React' 카테고리의 다른 글

[React] react hook form  (0) 2023.08.10
React Router V6  (0) 2023.08.02
리액트 총정리  (0) 2023.07.30
[React] Hooks 10개  (0) 2023.07.25
React + TypeScript 설치 방법  (0) 2023.07.20