[React with TypeScript] 타입스크립트로 리액트 상태관리하기
📄 타입스크립트로 리액트 상태관리하기
타입스크립트를 사용한 프로젝트에서 리액트 상태관리 훅을 사용하는 경우가 있습니다.
📄 1. useState 타입스크립트로 관리하기
useState
에 타입스크립트를 적용한 기본 구조는 다음과 같습니다.
// useState 타입스크립트 적용 기본 구조
useState<state의 type>(state 초기값);
// useState 예시 (카운터 예제)
const [count, setCount] = useState<number>(0);
이와 같이 Generics를 사용하여 상태의 타입을 설정합니다.
하지만 Generics를 사용하지 않아도 알아서 타입유추를 해주기 때문에 일일이 사용할 필요는 없습니다.
꼭 사용해야 하는 경우는 상태가 null
인 경우일 때입니다.
type Information = { name: string; description: string };
const [info, setInformation] = useState<Information | null>(null);
▪ useState를 적용한 코드에서 인풋상태 관리하기
타입스크립트를 적용한 코드는 각각 어떤 타입을 사용하는지 쉽게 알아낼 수 있습니다.
타입이 궁금한 값에 마우스를 갖다 대기만 하면 타입을 알려주기 때문입니다.
// src/MyForm.tsx
import React, { useState } from "react";
type MyFormProps = {
onSubmit: (form: { name: string; description: string }) => void;
};
function MyForm({ onSubmit }: MyFormProps) {
const [form, setForm] = useState({
name: "",
description: "",
});
const { name, description } = form;
const onChange = (e: any) => {
// 타입을 모를 때는 any로 설정합니다. 하지만 any타입은 최대한 지양해야합니다.
};
const handleSubmit = (e: any) => {};
return (
<form onSubmit={handleSubmit}>
<input name="name" value={name} onChange={onChange} />
<input name="description" value={description} onChange={onChange} />
<button type="submit">등록</button>
</form>
);
}
export default MyForm;
위 코드의 input
태그의 onChange
에 마우스 커서를 올려두면 타입스크립트가 타입을 알려줍니다..
onChange
의 타입은 Reaact.ChangeEventHandler<HTMLInputElement>
또는 undefined
라고 알려주고 있습니다..
🚨 주의할 점!!
여기서 주의할 점은 저 타입을 그대로 가져다 쓰면 에러가 난다는 것입니다.
e.target
에서 에러가 발생합니다.
타입 위에 Handler가 붙어 있어 에러가 발생했습니다.
Handler를 제거하고 React.ChangeEvent<HTMLInputElement>
로 타입을 지정해 에러가 발생하지 않게 작성해야 합니다.
onChange
와 마찬가지로 handleSubmit
의 타입을 지정해줍니다.
import React, { useState } from "react";
type MyFormProps = {
onSubmit: (form: { name: string; description: string }) => void;
};
function MyForm({ onSubmit }: MyFormProps) {
const [form, setForm] = useState({
name: "",
description: "",
});
const { name, description } = form;
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setForm({
...form,
[name]: value,
});
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
onSubmit(form);
setForm({
name: "",
description: "",
});
};
return (
<form onSubmit={handleSubmit}>
<input name="name" value={name} onChange={onChange} />
<input name="description" value={description} onChange={onChange} />
<button type="submit">등록</button>
</form>
);
}
export default MyForm;
📄 2. useReducer 타입스크립트로 관리하기
useReducer
를 사용하면 action
을 타입으로 만들어주고 타입의 액션을 OR
연산자를 사용하여 나열합니다.
type Action = { type: "INCREASE" } | { type: "DECREASE" };
액션 객체를 생성할 때 필요한 값을 타입안에 명시해주면
추후 리듀서를 사용할 때 자동완성이 되며 dispatch
할때 타입명시도 해주어 코드작성에 편리합니다.
// useReducer 사용 예시
import React, { useReducer } from "react";
type Color = "red" | "orange" | "yellow";
type State = {
count: number;
text: string;
color: Color;
isGood: boolean;
};
type Action =
| { type: "SET_COUNT"; count: number }
| { type: "SET_TEXT"; text: string }
| { type: "SET_COLOR"; color: Color }
| { type: "TOGGLE_GOOD" };
function reducer(state: State, action: Action): State {
switch (action.type) {
case "SET_COUNT":
return {
...state,
count: action.count, // count가 자동완성되며, number 타입인걸 알 수 있습니다.
};
case "SET_TEXT":
return {
...state,
text: action.text, // text가 자동완성되며, string 타입인걸 알 수 있습니다.
};
case "SET_COLOR":
return {
...state,
color: action.color, // color 가 자동완성되며 color 가 Color 타입인걸 알 수 있습니다.
};
case "TOGGLE_GOOD":
return {
...state,
isGood: !state.isGood,
};
default:
throw new Error("Unhandled action");
}
}
function ReducerSample() {
const [state, dispatch] = useReducer(reducer, {
count: 0,
text: "hello",
color: "red",
isGood: true,
});
const setCount = () => dispatch({ type: "SET_COUNT", count: 5 }); // count 를 넣지 않으면 에러발생
const setText = () => dispatch({ type: "SET_TEXT", text: "bye" }); // text 를 넣지 않으면 에러 발생
const setColor = () => dispatch({ type: "SET_COLOR", color: "orange" }); // orange 를 넣지 않으면 에러 발생
const toggleGood = () => dispatch({ type: "TOGGLE_GOOD" });
return (
<div>
<p>
<code>count: </code> {state.count}
</p>
<p>
<code>text: </code> {state.text}
</p>
<p>
<code>color: </code> {state.color}
</p>
<p>
<code>isGood: </code> {state.isGood ? "true" : "false"}
</p>
<div>
<button onClick={setCount}>SET_COUNT</button>
<button onClick={setText}>SET_TEXT</button>
<button onClick={setColor}>SET_COLOR</button>
<button onClick={toggleGood}>TOGGLE_GOOD</button>
</div>
</div>
);
}
export default ReducerSample;
출처
- 패스트캠퍼스 for velopert
Leave a comment