[React] 컴포넌트 간의 state 공유

뽕칠이·2024년 6월 28일
0

state 공유

Sometimes, you want the state of two components to always change together. To do it, remove state from both of them, move it to their closest common parent, and then pass it down to them via props. This is known as lifting state up, and it’s one of the most common things you will do writing React code.

때떄로, 두 컴포넌트의 state를 함께 변경하기를 원한다. 그렇게 하려면, 그 두 쌍에서 state를 제거하고, 가장 가까운 공톤 부모로 이동한 다음 props를 통해 전달한다. 이것은 state 끌어올리기 라고 알려져 있고, 리액트 코드를 작성할 때 가장 흔한 방법 중 하나이다.


state 공유 방법

react 공식 문서의 예제이다.

import { useState } from 'react';

const 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>
  );
}

function App() {
  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>
    </>
  );
}

export default App;

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

부모 컴포넌트에게 PannelisActive를 제어할 수 있는 권한을 부여한다.
-> 부모 컴포넌트가 isActivePanel에 props로 전달한다.

Panel컴포넌트에서 useState를 사용한 코드를 제거한다.

const [isActive, setIsActive] = useState(false);
-->
const Panel = ({ title, children, isActive}) => {...}

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

state를 부모 컴포넌트로 끌어올리려면 조정하려는 두 자식 컴포넌트의 가장 가까운 공통 부모 컴포넌트를 찾아야 한다.
가장 가까운 공통 부모 컴포넌트는 App컴포넌트다. App컴포넌트가 두 컴포넌트에 isActive 값을 전달할 수 있다.

import { useState } from 'react';

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

function App() {
  return (
    <>
      <h2>Almaty, Kazakhstan</h2>
      <Panel title="About" isActive={true}>
        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={true}>
        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>
    </>
  );
}

export default App;

3. 공통 부모에 state 추가

하나의 패널만 활성화하기 위해 활성화된 패널의 인덱스를 나타내는 state 변수를 사용한다.
state 변수 activeIndexApp컴포넌트 내부에 정의되어 있기 때문에 Panel컴포넌트는 직접 값을 설정할 수 없다. 이벤트 핸들러를 통해 props으로 전달하여 값을 변경해야 한다.

import { useState } from 'react';

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

function App() {
  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>
  );
}

export default App;

0개의 댓글