Hooks 가 functional component 의 API 야
Component가 함수라면 hook은 그 함수에 기억과 반응과 DOM 연결을 붙이는 장치야. 대부분의 일은 셋이 맡아: useState, useEffect, useRef.
각각이 내 chat 코드에 어떻게 등장하는지 보여줄게. 추상적 example 은 사람들이 hook 을 몇 년씩 잘못 쓰게 하는 방법이거든.
useState — 로컬 기억
모든 입력 박스, toggle, loading flag가 useState에 살아. 값이 바뀌면 React가 컴포넌트와 그 자손을 다시 그려. setter 함수는 render 사이에도 같은 참조를 유지해. reference equality 걱정 없이 자식에게 내려도 돼.
useEffect — render 밖으로 뻗기
render 후에 해야 하는 fetch, subscribe, scroll, document title 변경은 useEffect에 들어가. dependency array는 장식이 아니야. 빈 배열이면 mount 뒤 한 번 실행하고, 값이 들어 있으면 그중 하나가 바뀔 때 다시 실행해.
useCallback 으로 먼저 감싸거나, 컴포넌트 밖으로 옮겨. (cwkPippa 초기에 아빠가 이거 잡았어 — chat list 가 keystroke 마다 re-render 됐는데, effect dep 가 매번 fresh 한 arrow function 가리키고 있었거든.)
useRef — escape hatch
실제 DOM 노드 가리켜야 할 때 (input focus, list scroll, non-React 라이브러리 통합), useRef 가 stable 한 컨테이너 줘. .current는 바꿀 수 있지만 바꾼다고 re-render가 일어나진 않아. 그게 핵심이야. 화면 계약에 속하지 않는 값을 담아.
셋을 상태의 종류로 나누면 덜 헷갈려. 화면에 보여서 바뀌면 다시 그려야 하는 값은 state, render 뒤 외부 세계와 맞춰야 하는 일은 effect, render와 무관하게 같은 손잡이를 붙들어야 하는 값은 ref야. ref에 화면 값을 숨기거나 effect에서 계산 가능한 state를 또 만들면 React가 아니라 두 번째 상태 기계를 만든 셈이야. 영리해 보이지만 디버깅할 때 바로 이자를 받아.