공식문서의 마지막 장 !!
마지막 장이라고 하지만 , 이제 시작인 거 같은 느낌
Reusing Logic with Custom Hooks
공식문서에 있는 예시를 가져올까 하다가 , 기왕 하는거 직접 예시를 만들어보았다.
다음처럼 유저 아이디를 선택하면 RESTAPI
에 요청을 보내 유저의 이름과 , 유저의 투두 리스트를 받아오는 웹 페이지가 있다고 해보자
예제 API 서버는 jsonplaceholder 를 이용하였다.
이 때, userId
가 선택이 되면 유저의 이름을 구해오는 TodoTitle
컴포넌트와
투두 리스트를 가져오는 TodoContent
컴포넌트를 살펴보자
TodoTitle
Todocontent
두 컴포넌트 내부에서 사용되는 useEffect
문을 자세히 살펴보면 몇 가지 아쉬운 점들이 존재한다.
첫 번째로 두 컴포넌트에서 사용되는 useEffect
문은 생김새가 매우 비슷하다.
이를 하나의 함수로 정의해둔다면 , 불필요한 코드의 재사용을 방지 할 수 있을 것이고
같은 로직을 공유하는 새로운 컴포넌트를 추가 할 때에도 정의해둔 함수를 이용하면 좋을 것만 같다.
두 번째는 useEffect
문을 보았을 때 해당 useEffect
문이 어떤 역할을 하는지 한 눈에 보기 어렵다는 것이다.
어떤 결과값을 기대하고 사용한 useEffect
문인지 파악하기 위해선 블록문 내부의 코드 로직을 살펴보아야 한다는 것이다.
이는 해당 useEffect
문을 이용하는 컴포넌트의 역할을 한 눈에 이해하기 어렵게 만든다는 단점이 존재한다.
위에서 말한 아쉬웠던 점을 해결하기 위해 커스텀훅을 이용해보자
다음처럼 useFetching
이란 커스텀훅을 생성해주자
이는 고정된 주소에 queryString
값만 다르게 받아 받아온 결과값을
인수로 받은 callbackFn
의 인수로 넘겨줘 callbackFn
을 실행 시킨다.
이제 커스텀훅을 이용해서 동일한 로직을 사용하는 두 컴포넌트를 수정해보자
TodoTitle
Todocontent
두 컴포넌트의 중복된 로직을 하나의 커스텀훅인 useFetching
을 이용해줌으로서
중복된 코드의 재사용도 방지해줄 수 있었으며
컴포넌트 본연의 역할을 한 눈에 파악하기 더 쉬워졌다.
TodoTitle
은 userId
를 받아 해당 서브 쿼리문에 요청을 보내고 Name 을 바꾸는구나 ~ 이렇게 말이다.
물론
useCallback
에 의해서 조~금 지저분해지긴 했으나
만약useCallback
을 이용해주지 않으면useFetching
의deps
배열에 전해지는callbackFn
이
새롭게 생성됨에 의해 무한 요청을 보내게 될 것이다.
위 예시에서 보았듯 커스텀훅을 이용하면 가질 수 있는 장점이 존재한다.
커스텀훅은 사용하는 로직들을 블록문 안에 감추고 커스텀 훅의 이름만으로
어떤 작동을 하는지 알 수 있게 하는 추상화 를 가능하게 한다.
위 예시에서 보았듯 useFetching
이란 커스텀훅의 내부 로직을 모르더라도
사용 하는 예시를 보면 , 서브 쿼리문에 요청을 보내고 콜백 함수를 실행시킨다는 것을 알 수 있다.
중복되는 로직들을 하나의 모듈로 분리하여 관리하는 것은 코드의 가독성과 관리 용이성을 향상 시킨다.
각 컴포넌트에서 매번 중복되는 로직을 작성 할 필요가 없으며
로직의 변화가 필요할 경우 모듈로 관리되고 있는 해당 파일의 코드만 수정하면 되기에 관리 용이성을 향상 시킬 수 있다.
모듈화 해둔 커스텀 훅은 같은 로직을 필요로 하는 컴포넌트에서 재사용이 가능하다.
중복되는 코드를 매번 작성 할 필요 없이 위 예시처럼 import
해온 후 사용하면 되기 때문이다.
커스텀훅을 올바르게 이용하기 위해서는 다음 두 가지 조건을 지켜야 한다.
use
로 시작해야 한다.리액트에서 제공하는 훅 들은 몇 가지 조건을 가지고 있다.
예를 들어 리액트의 훅은 항상 컴포넌트 내부에서 호출되어야 한다.
외부에서 호출되는 훅은 오류를 발생시킨다.
이러한 오류는 리액트의 eslint
가 발생시키는 오류인데
use
로 시작하는 커스텀 훅 또한 동일한 eslint
를 적용 받기에 커스텀 훅임에도 불구하고
실제 리액트에서 제공하는 훅과 동일한 린팅을 받을 수 있다.
그 이유는 위와 동일하기 커스텀훅과 리액트의 훅을 동일시 하기 위함이다.
리액트의 훅을 하나 이상 호출하지 않는 경우엔 리액트의 훅과 동일시 될 수 없다.
그냥 하나의 함수에 불과하다.
이러한 함수를 리액트의 훅과 동일시 하여 린팅을 사용하게 되면 예기치 못한 에러를 마주 할 수 있으며
가독성과 유지보수성을 일관되게 유지하기 위해서는
항상 커스텀 훅과 리액트의 공식 훅을 동일시 가능하게 사용해야 한다.
위 예시에서 커스텀 훅을 어떤 행위를 하는 하나의 함수로만 사용하였지만
커스텀 훅의 활용은 무궁무진하다.
예를 들어 어떤 statefull value
를 반환하는 커스텀 훅의 예시를 보도록 하자
위 코드는 로컬 스토리지를 관리하는 커스텀 훅인데 로컬 스토리지를 어떻게 관리하느냐에 대한 내용보다
데이터의 상태 관리를 하는 useState , useReducer , useContext
등과 같은 공식 훅을
특정한 목적에 맞게 캡슐화 하여 데이터의 상태 관리 로직을 커스텀화 시킨다.
위
useLocalStorage
커스텀 훅을 보면 반환되는setter function
은
useState
에서 호출된setter function
이 아닌 커스텀 된setter function
이다.
등등 ..
더 자세한 내용은 외워봤자 어차피 기억 안날 것 같다.
직접 실습해보면서 생각해봐야할 거 같다. :)
어찌됐든 공식문서 react learn
시리즈는 끝~!