React Hook에 대해서
0
React Hook은 너무 추상적인 내용이라고 생각했다. 어딜가나 이게 어떤 역할을 하고, 어떤 규칙이 있고 이런 상세 내용은 알려주는 글은 많이 봤는데, 정확하게 이게 뭔지 정의하는 문구가 없었다. 리액트를 참 오래 써왔지만, 최근까지도 왜 Hook이 이런식으로 생겼는지, 왜 쓰는지 모르고 감각적으로 써왔다.
1
Hook을 이해하려면 과거로 돌아가야한다. 현재의 React가 아닌 Hook이 도입되기 이전 16.8버전 이전으로. 현대의 리액트 컴포넌트는 대부분 Functional Component로 만들어진다. 지금까지 와서야 Class Component를 쓰는곳은 레거시(16.8버전 이전) 전환이 끝나지 않은 곳 뿐이지 않을까. 그 시절에는 useState, useEffect같은 hook이 없었기에 functional Component를 쓰기 어려웠다. Class Component에는 강력한 도구인 state 와 React Lifecycle을 활용할 수 있는 componentDidMount 와 같은 함수들이 있었다.
2
이를 사용할 수 있게 만들어준것이 바로 React Hook이다. Functional Component 에서도 React의 기반인 state와 lifecycle을 사용할 수 있게 건져올린(Hook) 것이다.
// 이젠 잘 기억도 안나는 class Component..
class Tags extends React.Component {
contructor(props) {
super(props)
this.state = {tagString: 'None'};
}
changeText(str: string) {
this.setState({
tagString: str
});
}
componentDidMount() {
this.changeText('Mounted!')
}
componentDidUpdate() {
console.log('tagString is updated')
}
compoenentWillUnmount() {
console.log("I'll Die...");
}
render() {
return (
<div>{this.state.tagString}</div>
)
}
}useState와 useEffect를 사용하면 위 Class Component를 다음과 같이 간결하게 표현할 수 있다. 코드를 보며 주석을 통해 각 기능이 어떻게 대체되었는지 확인해보자.
export function Tags(props) {
// 1. this.state와 this.setState를 대체
const [tagString, setString] = useState('None');
// 2. componentDidMount 대체
// 의존성 배열([])이 비어있으므로 마운트 시 1회만 실행됨
useEffect(() => {
setString('Mounted');
// 3. componentWillUnmount 대체
// 컴포넌트가 사라질 때(Unmount) 실행되는 cleanup 함수
return () => {
console.log("I'll Die...");
};
}, []);
// 4. componentDidUpdate 대체
// tagString이 변할 때마다 실행됨
useEffect(() => {
console.log('tagString is updated');
}, [tagString]);
return <div>{tagString}</div>;
}
자세한 LifeCycle에 대한 설명은 아래 두 사이트를 참고.
첫 번째는 class Component, 두번째는 Functional Component입장에서의 Lifecycle.
https://ko.legacy.reactjs.org/docs/react-component.html https://ko.react.dev/learn/lifecycle-of-reactive-effects
[React.Component – React
A JavaScript library for building user interfaces
ko.legacy.reactjs.org](https://ko.legacy.reactjs.org/docs/react-component.html)
[React Effect의 생명주기 – React
The library for web and native user interfaces
ko.react.dev](https://ko.react.dev/learn/lifecycle-of-reactive-effects)
3
Custom Hook이란 다른 hook을 사용하고, convention이 지켜진 하나의 함수이다.
- use로 시작하는 함수일것.
- 함수 내 다른 Hook을 호출하여 사용할것.
그래서 대표적인 예시인 타이머 예시가 나온다. 아래 예제는 React의 state와 lifecycle을 react 기반으로 부터 꺼내와(hook) 사용하는 custom hook 예제이다.
export const useTimer = () => {
const [timer, setTimer] = useState(10)
useEffect(() => {
const interval = setInterval(() => {
setTimer(prev => {
if (prev <= 1) {
clearInterval(interval);
return 0;
}
return prev - 1;
});
}, 1000);
return () => clearInterval(interval);
}, []);
return {timer}
}
export const Timer = () => {
const {timer} = useTimer();
if(timer < 1) return <div>Time up!</div>
return <div>{timer}</div>
}4
이제야, React Hook을 정의할 수 있게 되었다. React Hook이란, React의 state, lifecycle, 그리고 렌더링 과정과 연결된 기능을 Functional Component에서도 사용하기 위해 React core에서 꺼내온(hook) 기능 이다. React의 중요 기능에 대한 정의조차 내리지 못하고 있던 나를 반성하며, 이 정의에서 파생되는 개념들을 설명하기 위한 글을 추가적으로 작성하고자 한다. lifecycle, state, virtual DOM 모두 아직 한 문장으로 정의하기는 아직은 어렵다.