이 글은 단순히 리액트 공식 문서를 읽고 베꼈을 뿐이다!! 학습 목적이라면 공식 문서를 보는 걸 추천한다.

공식 문서
https://react.dev/learn/reusing-logic-with-custom-hooks
Reusing Logic with Custom Hooks – React
The library for web and native user interfaces
react.dev
커스텀 훅: 컴포넌트끼리 로직 공유하기
인터넷 연결이 끊어졌을 때 알려 주는 로직을 생각해 보자. 연결 여부를 알려주는 상태값과 그걸 window
의 online
, offline
이벤트와 동기화하는 이펙트면 해결이 가능하다.
하지만 이 로직을 하나의 컴포넌트가 아니라 온갖 곳에서 써야 한다면 매번 이걸 적기에는 지치고 힘들 것이다. 이럴 때 나만의 커스텀 훅을 만든다면 여러 컴포넌트에서 우려먹을 수 있는 로직을 만들 수 있다.
컴포넌트에서 커스텀 훅 분리하기
- 반복되는 로직 대신 '그래서 결국 무엇이 필요한 건지' 적기
- '그걸 얻기 위해서 무엇을 해야 하는지'는 커스텀 훅 파일에 적기
- 선언형 프로그래밍: 컴포넌트는 세부 구현이 아니라 의도만을 보여줄 수 있음
리액트에서 이름 짓기 규칙
- 리액트 컴포넌트 이름은 대문자로 시작해야 함
- 훅 이름은
use
로 시작하는 camelCase로 써야 함
이 규칙은 컴포넌트를 딱 봤을 때 어디에 상태, 이펙트와 같은 리액트의 기능들이 숨어 있는지 알아보기 쉽게 도와준다.
렌더링 도중에 호출되는 모든 함수는 use
로 시작해야 하나요?
- ㄴㄴ
- 상태와 같은 리액트 기능을 사용할 때에만 붙이는 걸 권장함
- 사실 강제성이 있는 규칙은 아님
- 근데 유지보수를 고려했을 때
use
의 유무로 stateful logic 사용 여부를 판별할 수 있어서 지키는 게 좋음 - 관련 글: 아무 함수나 커스텀 훅이 될 수 있을까?
커스텀 훅은 상태 자체가 아니라 상태스러운 로직(stateful logic)을 공유한다
- 컴포넌트마다 커스텀 훅 내부의 상태는 독립적임
- A 컴포넌트의 커스텀 훅 내부의 상태가 변했다고 B 컴포넌트의 커스텀 훅 내부의 상태가 변하지 않음
- '로직'을 공유하는 거지 '값'을 공유하는 게 아님
- 물론 어떤 외부 시스템에 동기화했냐에 따라 값을 공유하는 것처럼 보일 수는 있음
- 만약 실제로 값을 공유해야 한다면 상태를 끌어올릴 것
훅에 반응형(리액트스러운) 값 전달하기
- 커스텀 훅 내부의 로직들은 컴포넌트가 리렌더링될 때마다 다시 실행됨 -> 커스텀 훅도 순수해야 함!!
- 컴포넌트 렌더링이랑 같이 실행되니까 커스텀 훅은 항상 최신 상태와 props를 인자로 받을 수 있음
커스텀 훅에 이벤트 핸들러 전달하기 (23.06.22 시점에서 실험적인 기능임)
- 커스텀 훅의 이펙트 내부에서 어떤 콜백을 실행해야 하는 경우 props로 넘겨줄 수는 있음
- 그리고 이펙트의 의존성 배열에 그 함수를 넣으면 됨
- 하지만 '함수'라서 의도치 않게 다시 선언되면 실제로는 똑같은 일을 하더라도 리액트가 볼 때는 의존성에 변화가 있다고 생각할 수 있음
- 실험적인 기능
useEffectEvent
사용 가능
커스텀 훅을 써야 할 때
- 모든 반복되는 코드를 다 커스텀 훅으로 분리할 필요는 없음
- 하지만 이펙트를 써야 하는 경우에는 한번쯤 고려할 만함: 이펙트는 외부 시스템과의 연결이니까
- 적절한 추상화를 이용해서 외부 시스템과 연결하는 이펙트를 훅으로 잘 만들 수 있음
커스텀 훅을 만들 때: 이름
- 이름 잘 짓기
- 명확한 이름이 안 떠오른다면 이펙트가 컴포넌트의 다른 로직과 너무 연관되어 있어 분리하기 힘들다는 뜻일 수 있음
- 코드를 거의 안 짜는 사람도 대충 무슨 일을 하는지 알 수 있을 만한 명확한 이름
- 외부 시스템 이름이 특이해서 커스텀 훅 이름이 이상해지는 건 괜찮음: 그 외부 시스템을 아는 사람이면 알아볼 수 있게끔 지으면 됨
커스텀 훅을 만들 때: 기능
- 고차원적인(high-level) 커스텀 훅을 만들기
useEffect
를 편하게 쓰기 위한 일종의 '컴포넌트 생명 주기' 훅을 만들지 않기useMount(fn)
같은 컴포넌트 생명 주기 훅은 리액트의 패러다임에 맞지 않음- 우선 리액트의 API를 써서 컴포넌트에 구현해 보고 나서 커스텀 훅으로 분리할지 고려
- 잘 만든 커스텀 훅은 그 훅의 기능을 적절하게 제한해서 코드를 선언적으로 만듦
커스텀 훅은 더 나은 패턴으로 옮길 때 좋다
- 이펙트는 비상탈출구: 리액트 밖으로 잠깐 벗어나야 하지만 리액트 기본 제공 기능을 쓰기에는 모자랄 때 사용
- 리액트 개발진들의 목표: 이펙트의 사용을 줄이기 위해 다양한 리액트 API를 제공하자
- 이펙트를 커스텀 훅으로 감싸면 나중에 리액트에서 새로운 기능을 제공했을 때 컴포넌트의 코드를 건드리지 않고 갈아타기 쉬움
- 커스텀 훅으로 감싼 이펙트는 코드에서 데이터의 흐름을 굉장히 명명백백하게 바꿔줌
- 컴포넌트가 구현이 아닌 의도에만 집중할 수 있게 도와줌
리액트에서 fetch에 관한 새로운 기능을 제공할 계획이 있나요?
- ㄱㄷ 계획은 있음
- 아래와 같은 느낌으로 바꾸지 않을까 생각중
import { use } from 'react'; // Not available yet!
function ShippingForm({ country }) {
const cities = use(fetch(`/api/cities?country=${country}`));
const [city, setCity] = useState(null);
const areas = city ? use(fetch(`/api/areas?city=${city}`)) : null;
// ...
'리액트 공식 문서 읽기' 카테고리의 다른 글
32화: useSyncExternalStore (0) | 2023.07.24 |
---|---|
31화: useState (0) | 2023.07.16 |
29화: Removing Effect Dependencies (0) | 2023.06.22 |
28화: Separating Events from Effects (0) | 2023.06.22 |
27화: Lifecycle of Reactive Effects (0) | 2023.06.22 |