hook은 리액트 16.8 버전부터 새롭게 출시된 기능으로, 클래스 컴포넌트 형식을 사용하지 않아도 state와 다른 리액트의 기능을 사용할 수 있다.
useState로 관리하는 변수의 값이 변경되면 컴포넌트의 재렌더링이 발생한다. 리액트 컴포넌트가 항상 최신의 상태를 반영하도록 도와준다.
function App(): JSX.Element {
const [counter, setCounter] = useState(0);
return (
<div className="App">
<button onClick={() => setCounter(prev => prev + 1)}>Click!</button>
{/* useState로부터 반환받은 state가 갱신되면 자동으로 페이지가 갱신된다. */}
{ counter }
</div>
);
}
export default App;
리액트에서 데이터의 흐름은 상위 컴포넌트에서 하위 컴포넌트 방향으로 흐른다. 만약 하위 컴포넌트의 변화가 상위 컴포넌트의 데이터에 영향을 미치게 하고 싶다면, 상위 컴포넌트의 useState로부터 반환받은 dispatch(setState) 함수를 prop으로 전달하는 방법을 사용할 수 있다.
// App.js
function App(): JSX.Element {
const [totalCount, setTotalCount] = useState(0);
const increaseTotalCount = () => setTotalCount((prev) => prev + 1);
const decreaseTotalCount = () => setTotalCount((prev) => prev - 1);
return (
<div className="App">
<h1>{totalCount}</h1>
{/*
onIncrease, onDecrease 프롭에 메서드를 전달한다.
setState 함수를 직접 전달하는 것을 지양한다.
*/}
<Counter
onIncrease={increaseTotalCount}
onDecrease={decreaseTotalCount}
/>
<Counter
onIncrease={increaseTotalCount}
onDecrease={decreaseTotalCount}
/>
<Counter
onIncrease={increaseTotalCount}
onDecrease={decreaseTotalCount}
/>
</div>
);
}
export default App;
redux를 이용한 전역 상태 관리, eventbus 사용 등 여러가지 방법이 있지만, 이 방법은 별도의 라이브러리 설치 없이 데이터를 다룰 수 있는 가장 간단한 방법이다.
useRef는 .current 프로퍼티로 전달된 초깃값(initialValue)로 초기화된 변경 가능한 객체(ref)를 반환한다.
타입스크립트에서 const inputRef = useRef()
형태로 사용하면 컴파일 에러가 발생한다! 이를 해결하기 위해서는 generic 정의가 필요하다.
useRef<T>(initialValue: T): MutableRefObject<T>
MutableRefObject
가 아닌 RefObject
가 반환된다. → dom을 조작하는데 사용할 수 있다.useRef<T>(initialValue: T|null): RefObject<T>
const inputRef = useRef<HTMLInputElement>(null);
// inputRef가 possibly null일 수 있으므로, type gurad를 통해 타입을 체크해야 한다.
const onClick = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
공통점
const [state, setState] = useState(initialValue)
에서 setState로 상태를 변경, state는 변경된 상태를 반환받음ref.current
에 값을 동적으로 할당차이점
useRef
는 단순히 DOM에 연결해서 DOM을 조작하기 위하여 사용하는 것인줄 알았는데, mutable하게 관리할 수 있음을 알았고, 재렌더링시에도 값이 유지됨을 알았다. 다만, 타입을 빡세게 지정해주어야 해서 다소 애를 먹었다.. 꼭 useRef<Element>(null)
형식을 지켜줘야 타입 스크립트에서 잘 인식하는 것 같다.TypeScript React에서 useRef의 3가지 정의와 각각의 적절한 사용법
useState vs useRef