TypeScript는 React와 함께 사용할 때 코드의 안전성을 높이고, 런타임 오류를 줄이는 데 큰 도움을 줍니다. 이 글에서는 TypeScript를 사용하여 React 컴포넌트에서 타입을 지정해야 하는 주요 항목들을 살펴보겠습니다.
컴포넌트에 전달되는 props
의 타입을 지정해야 합니다. 이를 통해 예상하지 못한 값이 전달되는 것을 방지할 수 있습니다.
type ButtonProps = {
label: string;
onClick: () => void;
disabled?: boolean; // 선택적 속성
};
const Button: React.FC<ButtonProps> = ({ label, onClick, disabled }) => {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
};
<Button label="Click Me" onClick={() => console.log("Clicked!")} />
useState
를 사용할 때 초기 값만으로는 타입을 유추하지 못하는 경우 타입을 명시적으로 지정해야 합니다.
import { useState } from "react";
const Counter = () => {
const [count, setCount] = useState<number>(0); // 숫자 상태
const [name, setName] = useState<string | null>(null); // 문자열 또는 null
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
이벤트 핸들러의 매개변수 타입을 지정하면, 어떤 이벤트가 발생했는지 명확히 알 수 있습니다.
const Input = () => {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value);
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log("Form submitted");
};
return (
<form onSubmit={handleSubmit}>
<input type="text" onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
};
useRef
를 사용할 때 기본적으로 null
일 가능성이 있으므로, 타입을 명시해야 합니다.
import { useRef } from "react";
const InputFocus = () => {
const inputRef = useRef<HTMLInputElement>(null);
const focusInput = () => {
inputRef.current?.focus(); // `current`가 null이 아닐 때만 focus
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>
</div>
);
};
외부 API로부터 데이터를 가져오거나, Axios 등의 라이브러리를 사용할 때 타입을 지정해야 데이터 구조를 명확히 알 수 있습니다.
type User = {
id: number;
name: string;
email: string;
};
const fetchUsers = async (): Promise<User[]> => {
const response = await fetch("/api/users");
return response.json();
};
const UserList = () => {
const [users, setUsers] = useState<User[]>([]);
useEffect(() => {
fetchUsers().then(setUsers);
}, []);
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
폼 데이터를 다룰 때 타입을 명시하면 필드 이름과 데이터 구조를 명확히 정의할 수 있습니다.
type FormData = {
username: string;
password: string;
};
const LoginForm = () => {
const [formData, setFormData] = useState<FormData>({
username: "",
password: "",
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
return (
<form>
<input name="username" onChange={handleChange} value={formData.username} />
<input name="password" type="password" onChange={handleChange} value={formData.password} />
<button type="submit">Login</button>
</form>
);
};
React Context를 사용할 때 타입을 지정하면 컨텍스트 값을 명확히 알 수 있습니다.
type Theme = "light" | "dark";
const ThemeContext = React.createContext<Theme>("light");
const App = () => {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
};
const Child = () => {
const theme = React.useContext(ThemeContext);
return <div>Current theme: {theme}</div>;
};
TypeScript와 React에서 타입을 지정해야 하는 주요 항목은 다음과 같습니다.
useState
로 관리하는 상태useRef
로 DOM 요소나 값을 참조할 때TypeScript를 활용하여 React 애플리케이션의 안정성과 가독성을 높여보세요!