useId 소개


useId는 React 18 버전에 도입된 훅으로, 노드의 트리 위치를 나타내는 고유 ID(Base32 문자열)를 반환한다. 컴포넌트 트리가 여러 자식(children)으로 분기될 때마다 ID에 추가 비트를 삽입해서 각 자식의 위치를 나타낸다.

:r0: (부모 컴포넌트)
:r1: (자식 컴포넌트1)
:r2: (자식 컴포너트2)
...

주로 서버 / 클라이언트에서 생성한 트리(tree) 사이의 하이드레이션(hydration) 불일치(mismatch)를 방지하기 위해 사용한다. 즉, useId가 생성한 고유한 ID를 이용해 원활한 하이드레이션을 돕는 목적인 것. 리스트의 key를 만들기 위한 목적이 아니므로 주의한다.

출력값 예시


<aside> <img src="/icons/search_gray.svg" alt="/icons/search_gray.svg" width="40px" /> : (콜론)은 querySelector 같은 CSS 셀렉터에선 지원하지 않는다(\\ 백슬래시로 이스케이프해서 사용할 수는 있다). useId는 : 토큰을 포함한 문자열을 생성하므로 CSS 셀렉터에선 사용할 수 없다.

</aside>

export default function App() { 
  const id = useId();
  return (
    <div>
      <h3>{`App - ${id}`}</h3> {/* App - :r0: */}
      <Child /> {/* Child - :r1: SubChild - :r2: */}
      <Child /> {/* Child - :r3: SubChild - :r4: */}
    </div>
  );
} // App.js

export default function Child() { 
  const id = useId();
  return (
    <div>
      <h3>{`Child - ${id}`}</h3>
      <SubChild />
    </div>
  );
} // Child.js

export default function SubChild() { 
  const id = useId();
  return <h3>{`SubChild - ${id}`}</h3>
} // SubChild.js
App - :r0:
Child - :r1:
SubChild - :r2:
Child - :r3:
SubChild - :r4:

참고로 동일 컴포넌트에서 useId 훅을 여러번 호출하면 각각 다른 ID를 생성한다.

// App.js
const id1 = useId();
const id2 = useId();
console.log(id1, id2) // :r0: :r1:

활용 예시


<label> ⇄ <input> 요소를 연결할 때 useId가 생성한 유니크 ID를 활용할 수 있다.

function Checkbox() {
  const id = useId();
  return (
    <>
      <label htmlFor={id}>Do you like React?</label>
      <input id={id} type="checkbox" name="react"/>
    </>
  );
};

여러 필드에 사용할 땐 유니크 ID + 접미사 방식으로 사용할 수도 있다.

function NameFields() {
  const id = useId();
  return (
    <div>
      <label htmlFor={id + '-firstName'}>First Name</label>
      <div>
        <input id={id + '-firstName'} type="text" />
      </div>
      <label htmlFor={id + '-lastName'}>Last Name</label>
      <div>
        <input id={id + '-lastName'} type="text" />
      </div>
    </div>
  );
}

참고글