📂 오늘 배운 내용
- React & TypeScript 프로젝트 세팅
- Props Type (1) Interface 사용하여 props 타입 정의 (2)선택적 Props
- useRef와 useState <T>Generic 개념
- Event 객체의 타입
React & TypeScript 사용하기
// 프로젝트 만들기
npx create-react-app {프로젝트 이름} --template typescript
- TypeScript 오류 해결하기👾
추가하기
Props Type
- props란?
- react에서 컴포넌트 간 데이터 전달하기 위해 사용되는 객체
- 상위 컴포넌트에서 하위 컴포넌트로 데이터 전달할 때 사용
- Props와 Interface
Props를 이용해서 데이터를 상위 컴포넌트에게 받을 때는 props가 어떤 형태로 넘어오는 지 type 미리 적어줘야함
-예제
[src/ pages/ Lecture.tsx]
import {
PropsType1,
PropsType2,
PropsType3,
} from '../components/lecture/PropsType';
import Container from '../components/lecture/Container';
import SetText from '../components/lecture/SetText';
import EventObj from '../components/lecture/EventObj';
import TodoList from '../components/lecture/TodoList';
export default function Lecture() {
return (
<main>
<PropsType1 name='suyeon' />
<PropsType2 width='100px' color='red' height='100px' />
<PropsType3 width='100px' height='50px' text='hi' />
<PropsType3 width='100px' height='50px' text='hi' color='red' />
<Container>
<SetText />
<EventObj />
<TodoList />
</Container>
</main>
);
}
[src/components/lecture/Container.tsx]
interface Props {
// React 컴포넌트, JSX 요소, 문자열 등 모든 노드를 허용
children: React.ReactNode; // <div></div>
}
export default function Container({ children }: Props) {
return <div style={{ border: '1px dotted green' }}>{children}</div>;
}
[src/components/lecture/ PropsType.tsx]
1. inteface를 사용하여 props의 타입을 정의
: TypeScript에서는 `props`의 타입을 더 명확하게 지정하기 위해 Interface 사용
// 인터페이스 정의
// - 함수의 매개변수의 타입이니까 밖에서!
interface Props {
name: string;
}
// PropsType1 컴포넌트
// - 구조분해할당 사용하여 props 객체에서 name만 추출
export function PropsType1({ name }: Props) {
return (
<>
<h2>hello {name}</h2>
</>
);
}
interface Square {
// 모든 key는 string이고, value도 string이어야 함
[key: string]: string;
}
// props 객체를 매개변수로 받아, div 스타일을 동적으로 설정하는 컴포넌트
export function PropsType2(props: Square) {
const divStyle = {
width: props.width,
height: props.height,
backgroundColor: props.color,
};
return <div style={divStyle}></div>;
}
2. props를 선택적(optional)으로 만들기
: 물음표(?)를 사용해서 선택적 Props로 만들기
interface Square2 {
width: string;
height: string;
color?: string;
text: string;
}
// 구조분해 할당을 사용하여 props 객체에서 width, height, color, text 추출
export function PropsType3(props: Square2) {
const { width, height, color, text } = props;
const divStyle = {
width: `${width}`,
height: `${height}`,
// ? 처리된 속성에 대해 예외 처리 해주어야함
backgroundColor: `${color ? color : 'pink'}`,
lineHeight: `${height}`,
// textAlign: 'center',
};
return <div style={divStyle}>{text}</div>;
}
useRef와 useState
useState
- 화면이 변경되어야 하는 값 저장할 때 사용
- `useState<T>` 는 일반적으로 생략 가능하지만, `null | 타입`이 올 수 있을 때는 generic 사용
useRef
- 렌더링과 관계 없는 값(변수, DOM 요소 등) 저장할 때 사용
- `useRef<T>` 는 DOM 요소 접근 시 Generic 활용하여 타입 안정성 높일 수 있음
- `useState<T>` Generic 개념
// 예제
const [count, setCount] = useState<number>(0); // count는 number 타입
const [text, setText] = useState<string>(''); // text는 string 타입
// 예제2: SetText.tsx
const [text, setText] = useState('');
- useState는 기본적으로 초기값의 타입을 추론하므로 일반적으로 Generic 작성할 필요 없음
- 예제2에서 Generic 생략했지만 타입스크립트가 `''`(빈 문자열)을 보고 자동으로 text를 String 타입으로 추론함
// generic을 명시적으로 쓰는 경우
const [data, setData] = useState<null | Data>(null);
- null을 포함한 유니언 타입 정의할 때는 generic을 활용하는 것이 유용함
- 위 코드에서 generic은 Null일 수도 있고, Data 타입을 가질 수도 있는 상태
- `useRef<T>` Generic 개념
useRef는 2가지 목적으로 사용됨 :
- 값을 저장하는 변수처럼 사용( 예제 SetText.tsx의 `refVal`변수)
- DOM 요소에 접근 (예제 SetText.tsx의 `refInput` 변수)
- 예제
[src/components/lecture/ container.tsx]
import React from 'react';
interface Props {
children: React.ReactNode; // <div></div>
}
export default function Container({ children }: Props) {
return <div style={{ border: '1px dotted green' }}>{children}</div>;
}
[src/components/lecture/ setText.tsx]
import { useRef, useState } from 'react';
export default function SetText() {
// [1] useState<T> Generic
// const [text, setText]= useState<string>('');
const [text, setText] = useState('');
// [2] useRef<T> Generic
// - useRef는 값이 변경되어도 컴포넌트를 리렌더링하지 않는 훅
//- ref 객체를 이용해서 DOM 접근 시 null 초기값 전달 필수
const refVal = useRef<number>(0); //변수로 사용할 ref
const refInput = useRef<HTMLInputElement>(null); // DOM 요소 접근
// [2-1] refVal 변수를 변경하는 함수
// - refVal.current 값이 변경되지만, 리렌더링 발생 x
const changeRef = () => {
refVal.current += 1;
console.log('refVal:', refVal.current);
};
// [2-2] refInput DOM 요소 접근
// - 사용자가 입력한 값을 가져와 state 값 변경
const changeState = () => {
if (refInput.current) {
console.log('text state 변경 완료!');
setText(refInput.current.value);
}
};
// [3] 현재 상태와 input 값 확인 함수
const checkString = () => {
console.log('state string', text); //현재 state 값
console.log('input value ref', refInput.current?.value); //현재 input 값
};
return (
<div>
<h2>useRef & useState 사용해보기</h2>
<input type='text' ref={refInput} onChange={checkString} />
<br></br>
{/* input 값 -> state 저장 */}
<button onClick={changeState}>state 변경!</button>
{/* ref 값 증가 */}
<button onClick={changeRef}>ref +1</button>
{/* 현재 state 값 */}
<p>state: {text}</p>
{/* refVal 값이 변경되지만 리렌더링 발생 x */}
<p>refVal: {refVal.current}</p>
{/* 현재 input 값 */}
<p>refInput의 value: {refInput.current?.value}</p>
</div>
);
}
Event 객체의 Type
- React에서 이벤트 객체란?
- HTML 요소에서 이벤트가 발생하면, 해당 이벤트에 대한 정보가 이벤트 객체(event object)에 담김
- 이벤트 객체를 통해 클릭된 요소(e.target), 입력값(e.target.value), 눌린 키(e.key) 등의 정보를 얻을 수 있음
이벤트별 주요 속성
이벤트 | 주요 속성 |
click | e.target, e.currentTarget |
keydown | e.key, e.code |
change | e.target.value (input 요소의 값) |
- 이벤트 객체 타입 지정 방법
이벤트마다 타입의 이름이 다름
타입스크립트에서는 이벤트 객체의 타입을 명확히 지정해야 오류 없이 사용 가능
이벤트 | 타입 |
onClick | React.MouseEvent<HTMLElement> |
onChange | React.ChangeEvent<HTMLInputElement> |
onKeyDown | React.KeyboardEvent<HTMLINputElement> |
- 예제
[EventObj.txs]
import React from 'react';
export default function EventObj() {
function handleClick(e: React.MouseEvent<HTMLElement>) {
console.log(e);
console.log(e.target);
// console.log(e.target.value);//에러 changeEvent가 아니라서 value 없음
}
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
console.log(event);
console.log(event.target.value);
}
function handleKeyDown(a: React.KeyboardEvent<HTMLInputElement>) {
console.log(a.key);
console.log(a.code);
// console.log(a.KeyCode); //legacy keyCode는 더 이상 사용되지 않음
}
return (
<div style={{ backgroundColor: 'yellow' }}>
{/* onClick 내에서 event 전달받을 때는
이벤트 타입 작성하지 않아도 됨 */}
<div onClick={(e) => console.log(e)}>onClick(익명함수)</div>
<div onClick={handleClick}>onClick(함수 호출)</div>
<div>
<span>onChange</span>
<input type='text' onChange={handleChange}></input>
</div>
<div>
<span>onKeyDown</span>
<input type='text' onKeyDown={handleKeyDown}></input>
</div>
<div onDrag={handleClick}>onDrag</div>
</div>
);
}
💡 클릭 이벤트
- onClick 이벤트 핸들러 정의할 때, 익명함수 안에서 이벤트 객체를 받을 경우 타입 지정 필요 없음
- 타입스크립트가 자동으로 타입 추론 가능
1. 이벤트 핸들러를 직접 함수로 정의한 경우 (타입 필요)
function handleClick(e: React.MouseEvent<HTMLElement>) {
console.log(e); // 이벤트 객체 출력
console.log(e.target); // 클릭된 요소 출력
}
// return
<div onClick={handleClick}>onClick(함수 호출)</div>
- 별도의 이벤트 핸들러 함수로 분리하는 경우 타입스크립트가 `e`의 타입 자동 추론 불가하므로, 타입 직접 명시
- 함수의 매개변수(e)에 타입 명시적으로 지정해야함
2. 이벤트 핸들러를 익명 함수로 전달한 경우 (타입 생략 가능)
<div onClick={(e) => console.log(e)}>onClick(익명함수)</div>
- 익명 함수 안에서 이벤트 객체를 직접 받는 경우 타입스크립트가 e 의 타입 자동 추론
✍🏻 회고
🌐 참고
서울시 청년취업사관학교(SeSAC) x 코딩온 웹 개발자 풀스택 과정
29.react-typescript
'Today I Learned > SeSAC 웹 2기' 카테고리의 다른 글
Node.js Socket.io 라이브러리(EJS) 💬💬 | 15주차(2) (0) | 2025.02.08 |
---|---|
Node.js Web Socket 💬 | 15주차(1) (0) | 2025.02.05 |
Typescript 입문 🥳 | 13주차(2) (0) | 2025.01.24 |
React 상태관리 ContextAPI와 Redux | 13주차(1)하 (0) | 2025.01.23 |
React Router | 13주차(1)상 (1) | 2025.01.23 |