컴포넌트 간 상태 공유하기

컴포넌트 간 상태 공유하기

두 컴포넌트의 상태가 항상 함께 변하길 원할 때가 있어요. 방법은 간단해요. 두 컴포넌트에서 상태를 빼내어 가장 가까운 공통 부모로 옮기고, props로 내려주는 것이에요. 이를 "상태 끌어올리기(lifting state up)"라고 하고, React 코드를 짤 때 가장 흔하게 하는 일 중 하나예요.

출처: https://react.dev/learn/sharing-state-between-components

예시로 보는 상태 끌어올리기

부모 Accordion 컴포넌트가 두 개의 별도 Panel을 렌더링하는 예시를 볼게요. 각 Panel은 내용이 보이는지 결정하는 boolean isActive 상태를 가져요.

각 패널의 버튼을 누르면 그 패널의 isActive 상태만 바뀌어요. 그런데 "한 패널을 열면 다른 패널은 닫힌다"처럼 두 패널이 함께 동작하길 원한다면 상태를 공유해야 해요.

1단계: 자식 컴포넌트에서 상태 제거하기

Panel의 상태를 부모로 옮기면, 이제 부모가 isActive를 prop으로 내려주며 제어할 수 있어요. 반대로 PanelisActive 값에 대한 제어권을 잃어요.

2단계: 공통 부모에서 하드코딩된 값 내려주기

상태를 끌어올리려면 두 자식 컴포넌트의 가장 가까운 공통 부모를 찾아야 해요. 예시에서는 Accordion 컴포넌트예요. 두 패널 위에 있고 props를 제어할 수 있으니, 현재 활성 패널이 누구인지의 "진실의 원천(source of truth)"이 돼요.

3단계: 공통 부모에 상태 추가하기

Accordion이 두 패널의 isActive 값을 담당하게 되고, 이후 이벤트 핸들러를 내려주면 자식이 부모의 상태를 바꿀 수 있어요.

제어된(controlled) vs 비제어(uncontrolled) 컴포넌트

일부 로컬 상태를 가진 컴포넌트를 "비제어(uncontrolled)"라고 불러요. 예를 들어 isActive 상태 변수를 가진 원래 Panel은 부모가 패널 활성 여부에 영향을 줄 수 없으니 비제어예요. 반대로 props로 구동되는 컴포넌트는 "제어(controlled)"라고 해요.

각 상태의 진실의 원천

각 고유한 상태 조각에 대해, 그 상태를 "소유"하는 컴포넌트를 하나 정해요. 이것이 "단일 진실의 원천(single source of truth)" 원칙이에요. 모든 상태가 한 곳에 있으라는 뜻이 아니라, 각 상태 조각마다 그 정보를 담당하는 특정 컴포넌트가 하나는 있어야 한다는 뜻이에요. 공유 상태를 컴포넌트 사이에 복제하지 말고, 공통 부모로 끌어올려서 필요한 자식에게 내려주는 거예요.

앱을 만들며 상태의 위치는 자주 움직여요. 어느 상태가 어디에 "살지" 파악하는 동안 상태를 내렸다 올렸다 하는 건 정상적인 과정이에요.

요약

  • 두 컴포넌트를 조정하고 싶으면 그들의 상태를 공통 부모로 옮겨요.
  • 그러고 나서 공통 부모에서 props를 통해 정보를 내려줘요.
  • 마지막으로 이벤트 핸들러를 내려줘서 자식이 부모의 상태를 바꿀 수 있게 해요.
  • 컴포넌트를 props로 구동되는 "제어(controlled)" 상태인지, state로 구동되는 "비제어(uncontrolled)" 상태인지로 보는 게 유용해요.

더 알아보기