개인적으로 생각할 때 가장 못생긴 hook은 useEffect다. 비슷하게 생긴 useMemo는 이름만 만나도 반환하고 기억하는 값이 있겠구나!하고 짐작 할 수 있다. useCallback은 컴포넌트가 다시 마운트될 때 쓸데없는 함수를 새로 만들지 않게 하기 위해서구나 하고 짐작할 수 있다.
useEffect는 그냥 뭔가가 일어나고 렌더링이 새로 일어나겠구나. 하는 것밖에 알 수가 없다. 그 안의 콜백 함수를 보아야 비로소 그 '일어나는 일'을 짐작할 수 있게 되는 것이다.
순서가 조금 바뀌었지만 useEffect는 lifecycle method를 대신해 sideEffect가 있는 코드를 처리하는 역할을 한다. 사소하게는 console.log부터 백엔드와의 통신까지, 리액트 외부와 간섭하거나 실행할 때마다 값이 바뀔 수 있는 작업을 처리하는데 특화되어있다. (*주 : lifecycle method에 대한 설명은 (2)에서 변할 것이다.)
가장 단순한 방법은 useEffect의 내부 로직을 커스텀 훅으로 독립시키는 것이다. useEffect의 를 사용하는 대신 커스텀 훅을 사용하므로서 인터페이스화 시켜 내부 로직을 몰라도 어떤 값을 가져올 지 알 수 있도록 설계하는 것이다.
// before
function Component() {
useEffect(() => {
//something...
}, [])
return <div>
//...
</div>
}
// after
function Component() {
const userData = useUserDate();
return <div>
//...
</div>
}
function useUserData() {
useEffect(() => {
// something...
}, [])
return { userData }
}
이 때 커스텀 훅의 선언 방식에 따라 차이점이 발생한다.
함수 선언문으로 선언하는 경우 호출과 선언 순서가 달라져도 함수는 문제 없이 작동한다. 그러나 표현식으로 선언할 경우 문이 아니기 때문에 코드의 선언과 호출 순서가 중요해진다.
따라서 표현식으로 선언하게되면 함수 컴포넌트를 하단에 선언해야 하기 때문에 가독성이 나빠질 수 있다. 리팩터링 2판과 web dev simplified에서 둘 다 함수 선언문으로 기술한 것을 근거로 판단하건데 커스텀 훅은 이하의 원칙을 세워 사용하기로 한다.