간단한 구구단, 끝말 잇기 게임을 구현해보면서 useState
, useRef
, useCallback
, Event Hanlder
는 어떻게 타이핑되는지 알아보자.
useState
를 사용할 때는 useState<타입>()
과 같이 Generics
를 사용하여 해당 상태가 어떤 타입을 가지고 있는지 설정하면 된다.
const [first, setFirst] = useState<number>(Math.ceil(Math.random() * 9));
const [second, setSecond] = useState<number>(Math.ceil(Math.random() * 9));
const [value, setValue] = useState<string>("");
const [result, setResult] = useState<string>("");
✅ 참고로 useState
를 사용할 때는 Generics
를 사용하지 않아도 타입을 추론하기 때문에 생략해도 상관없다.
그렇다면 어떤 상황에서 Generics을 사용하는 것이 좋을까?
✅ 상태가 null
일 수도 있고 아닐 수도 있는 상황에서는 Generics
를 활용하면 좋다.
<Example>
type Information = { name: string; description: string };
const [info, setInformation] = useState<Information | null>(null);
✅ 상태의 타입이 까다로운 구조를 가진 객체이거나 배열일 때는 Generics
를 명시하는 것이 좋다.
<Example>
type Todo = { id: number; text: string; done: boolean };
const [todos, setTodos] = useState<Todo[]>([]);
💡 중요) useState에 빈 배열
[]
이 초기화되는 경우
useState
초기 값을 빈 배열로 할 경우, 타입스크립트에서는 빈배열[]
을never type
으로 인식한다.
never type
: 함수의 끝에 절대 도달하지 않는다는 의미를 지닌 타입
✅ 따라서 구체적인 타입을 지정해줘야 한다.
TryInfo
는Interface
useRef
는 리액트 컴포넌트에서 외부 라이브러리의 인스턴스 또는 DOM 을 특정 값 안에 담을 때 사용된다. 추가적으로, 이를 통해 컴포넌트 내부에서 관리하고 있는 값을 관리할 때 유용한다.
✅ ref
를 사용 시 어떤 타입을 사용할지 헷갈리면 타입추론된 타입을 확인하면 된다.
✅ useRef
를 사용 할 땐 Generics
로 타입을 정한다.
✅ useRef
를 사용하여 DOM
에 대한 정보를 담을 땐, 초깃값을 null
로 설정한다.
✅ inputRef.current
안의 값을 사용 하려면 null 체킹을 해주어야 한다.
즉, 특정 값이 정말 유효한지 유효하지 않은지 체크하는 것이다. 타입스크립트에서 만약 어떤 타입이 undefined
이거나 null
일 수 있는 상황에는, 해당 값이 유효한지 체킹하는 작업을 꼭 해주어야 자동완성도 잘 이루어지고, 오류도 사라진다.
타입스크립트 환경에서 useRef
를 통해 어떤 변수 값을 관리하고 싶을 땐 다음과 같은 코드를 작성.
const id = useRef<number>(0);
const increaseId = () => {
id.current += 1;
}
✅ useRef
를 쓸땐 위와 같은 코드처럼 Generic
을 통해 ~.current
의 값을 추론 가능.
1️⃣ 이벤트 인자 타입을 지정하려면 먼저 이벤트의 타입을 찾는다.
2️⃣ 이벤트의 타입을 찾았다면, 해당 이벤트를 발생시키는 요소를 제네릭 인자로 전달한다.
해당 코드에서는 onChange
의 e
객체의 타입을 지정해야 한다.
하지만 e
객체의 타입이 무엇인지 외울 필요 없다. 왜냐하면 타입추론에 의해서 어떤 타입을 구현해야 할지 알려준다.
✅ 따라서, 다음과 같이 이벤트 타입과 제네릭을 지정할 수 있다.
✅ submit
역시 다음과 이벤트 타입과 제네릭을 지정할 수 있다.
💡 이처럼 타입추론에 의해 설정이 간편하다.
✅ 그리고
ChangeEvent
,FormEvent
이외에도 역할에 따른 여러 이벤트 타입이 존재한다.
✅ 또한,
input Element
,form Element
이외에도 여러 HTML 노드의 타입이 존재한다.
useCallback
은 메모제이션된 함수를 반한하는 하는 함수로, 특정 함수를 새로 만들지 않고 재사용하고 싶을 때 사용한다.
따라서, 앞서 본 Event Hanlder함수들
을 useCallback
으로 감싸주어서 불필요한 렌더링을 방지하고 성능을 최적화 한다.
✅ 이때 useCallback
으로 한번 감싸줬기 때문에 타입 추론이 안된다. 즉, handler
를 useCallback
으로 wrapping
하면 e
가 type을 잃는다. 따라서 해결할 수 있는 방법은 2가지이다.
방법 1: event object에 직접 typing
const onChangeHandler = useCallback((e: React.FormEvent)=>{}, [])
방법 2 : useCallback의 generic 으로 typing
generic
은 가독성이 낮아진다.const onChangeHandler = useCallback<(e: React.FormEvent) => void>((e)=>{}, [])
참조 및 참고하기 좋은 사이트