(준)공식 문서/React

[ React 공식문서 ] state 관리하기 (4) : 컴포넌트 간의 state 공유

Je-chan 2024. 3. 11. 12:56

1. 예제로 알아보는 state 끌어올리기

import { useState } from 'react';

function Panel({ title, children }) {
  const [isActive, setIsActive] = useState(false);
  return (
    <section className="panel">
      <h3>{title}</h3>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button onClick={() => setIsActive(true)}>
          Show
        </button>
      )}
    </section>
  );
}

export default function Accordion() {
  return (
    <>
      <h2>Almaty, Kazakhstan</h2>
      <Panel title="About">
        With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city.
      </Panel>
      <Panel title="Etymology">
        The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild <i lang="la">Malus sieversii</i> is considered a likely candidate for the ancestor of the modern domestic apple.
      </Panel>
    </>
  );
}
  • 이 코드에서 한 Pannel 의 버튼을 눌러도 다른 패널에 영향을 주지 않고 독립적으로 동작한다.
  • 그렇다면, 이제 한 번에 하나의 패널만 열리도록 하려면 어떻게 해야 할까?

Step 1 : 자식 컴포넌트에서 state 제거

  • 부모 컴포넌트에서 Panel 의 isActive 를 제어할 권한을 부여해야 한다.
  • 자식 컴포넌트에서 isActive 를 제거하고 props 로 넘겨받는 방식으로 코드를 변경한다
function Panel({ title, children, isActive }) {

}

Step 2 : 공통 부모에 하드 코딩된 데이터 전달하기

  • state 를 끌어 올리려면 이 state 를 공유하는 컴포넌트의 가장 가까운 컴포넌트를 찾아야 한다.

Step 3 : 공통 부모에 state 추가

  • state 를 끌어 올리려면 state 로 저장하는 항목의 특성이 변경되는 경우가 많다.
const [activeIndex, setActiveIndex] = useState(0);
  • 각 Panel 에서 “Show” 버튼을 클릭하면 Accoordian 의 활성화된 인덱스를 변경해야 한다.
  • Accordion 컴포넌트는 이벤트 핸들러를 prop 으로 전달해서 Panel 컴포넌트가 state 를 변경할 수 있도록 명시적으로 허용해야 한다.
import { useState } from 'react';

export default function Accordion() {
  const [activeIndex, setActiveIndex] = useState(0);
  return (
    <>
      <h2>Almaty, Kazakhstan</h2>
      <Panel
        title="About"
        isActive={activeIndex === 0}
        onShow={() => setActiveIndex(0)}
      >
        With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city.
      </Panel>
      <Panel
        title="Etymology"
        isActive={activeIndex === 1}
        onShow={() => setActiveIndex(1)}
      >
        The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild <i lang="la">Malus sieversii</i> is considered a likely candidate for the ancestor of the modern domestic apple.
      </Panel>
    </>
  );
}

function Panel({
  title,
  children,
  isActive,
  onShow
}) {
  return (
    <section className="panel">
      <h3>{title}</h3>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button onClick={onShow}>
          Show
        </button>
      )}
    </section>
  );
}

제어(controlled) 및 비제어(uncontrolled) 컴포넌트

  • 일반적으로 일부 로컬 state 를 가진 컴포넌트를 “비제어 컴포넌트”라고 부른다.

2. A Single Source of Truth (for each state)

  • 일명 SSOT
  • React 애플리케이션은 많은 고유 state 를 가지고 있다.
  • 개발을 한다면 각 고유한 state 들에 대해 해당 state 를 소유하는 컴포넌트를 선택하게 된다.
  • 앱은 작업하면서 계속 변경된다. 각 state 의 위치를 파악하는 동안 state 를 아래로 이동하거나 백업하는 것이 일반적이다.

Reference

 

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

 

Sharing State Between Components – React

The library for web and native user interfaces

react.dev

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

 

컴포넌트 간의 state 공유 – React

The library for web and native user interfaces

react-ko.dev