이번 시간에는 타입스크립트 환경에서 리액트 Hooks를 사용하는 방법에 대해서 알아보겠습니다.
컴포넌트의 Hello, World라고 할 수 있는 카운터를 만들어보죠.
src/Counter
function Counter() {
const [counter, setCounter] = useState<number>(0);
const onIncrease = () => setCounter(counter + 1);
const onDecrease = () => setCounter(counter - 1);
return (
<div>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
{counter}
</div>
);
}
useState()
를 사용할 때 제네릭으로 타입 인수를 넘겨 state의 타입을 명시했습니다. 하지만 타입스크립트에서는 인수를 보고 타입을 추론하기 때문에 <number>
을 쓰지 않아도 "아 state는 number이구나" 라고 컴파일러가 추론할 것 입니다. 그럼 어떤 상황에서 제네릭으로 타입을 명시하는게 좋을까요?
상태가 null
을 가질수도 있거나 객체, 배열일 경우에 이를 명시하는 것이 좋습니다.
// 이렇게 null 값을 가질 수도 있는 경우
type Info = {name: string; description: string}
const [info, setInfo] = useState<Info | null>(null);
// 객체, 배열일 경우
type Todo = {id: number; text: string; done: boolean};
const [todos, setTodos] = useState<Todo[]>([]);
useReducer
Hooks를 사용하는 경우에는 액션을 타입으로 정할 때 |
을 써서 나열해주면 됩니다. 아래와 같이 말이죠.
type Action = {type: "INCREASE"} | {type: "DECREASE"};
function reducer(state: number, action: Action): number {
switch (action.type) {
case "INCREASE":
return state + 1;
case "DECREASE":
return state - 1;
default:
return state;
}
}
그리고 리듀서 함수에서는 state
와 반환하는 값의 타입을 일치시켜주는 것이 좋습니다. 이렇게 설정해두면 나중에 실수를 방지할 수 있기 때문이죠. 여기서는 number
로 일치시켜줬네요?
어떤 값을 직접 관리하고 싶을때 useRef
Hook을 사용하죠. 다음과 같이요.
const id = useRef<number>(0);
const increaseId = () => {
id.current += 1;
}
useRef
로 정한 DOM에 접근하기 위해서 current
프로퍼티로 접근해야 된다는 것을 잊지마세요.
실제로 DOM을 조작하기 위해서 useRef
에 제네릭으로 DOM의 타입을 명시해주면 좋습니다.
function MyForm({onSubmit: MyFormProps}) {
const inputRef = useRef<HTMLInputElement>(null);
}
HTMLInputElement
와 같은 타입을 알고 싶으면 DOM 태그에 커서를 올려보세요. vscode에서 타입을 알려줍니다.
또한 useRef
를 사용해서 DOM 정보를 담을 때, 초깃 값으로 null
을 설정하고 current
로 값을 사용할 때 항상 null
체킹해주세요! 중요합니다. 그럼 오늘 배운 것을 요약해보죠.
useState
useReducer
|
로 나열하기useReducer
를 사용하면 자동완성, 타입체킹이 매우 잘 됨useRef
null
체킹하기https://velog.io/@velopert/using-hooks-with-typescript | 타입스크립트로 리액트 Hooks 사용하기 (useState, useReducer, useRef)