React Learn - 컴포넌트간 state 를 공유하는 방법

ChoiYongHyeun·2024년 2월 23일
0

리액트

목록 보기
5/31

공식문서를 크게 크게 한 챕터씩 정리하다가

3번째 챕터인 Managing State 부분부터는 한 강의 내용이 슬슬 깊어지는 듯 하여

한 강씩 정리하려고 한다.

Sharing State Between Components


Lifting state up by example

컴포넌트 내부에서 state 를 정의하고 컴포넌트가 내부 state 를 참조하는 JSX 객체를 반환함으로서

상태에 따른 렌더링 로직을 구현해왔다.

import { useState } from 'react';
import './App.css';
export default function App() {
  return (
    <>
      <h1>Title 입니다</h1>
      <Panel>나는 Panel 1입니다</Panel>
      <br />
      <Panel>나는 Panel 2입니다</Panel>
    </>
  );
}

function Panel({ children }) {
  const [isActive, setIsActive] = useState(false);

  return (
    <div className='container'>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button
          onClick={() => {
            setIsActive(true);
          }}
        >
          show
        </button>
      )}
    </div>
  );
}

이렇게 했을 때 Panel 1 이 보일 때에는 Pannel 2 가 보이지 않고 그 반대도 가능하게 하려면 어떻게 할까 ?

function Panel({ children }) {
  // Panel 의 state 는 각 컴포넌트 별 고유하게 가지고 있다.
  // 이런 local state 는 컴포넌트 내부만 참조 가능하다.
  const [isActive, setIsActive] = useState(false);

  return (
    <div className='container'>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button
          onClick={() => {
            setIsActive(true);
          }}
        >
          show
        </button>
      )}
    </div>
  );
}

우선 각 컴포넌트가 서로의 state 를 공유해야 하기 위해서는 각자가 서로 동일한 statesetter function 을 받아야 한다.

현재의 컴포넌트는 컴포넌트 내부에서 정의된 state 만 참조하기에 서로의 state 는 공유가 불가능하다.

서로 공유 가능한 state, setter function상위 컴포넌트에서 정의 해준 후

하위 컴포넌트에게 props 로 건내주게 되면 두 컴포넌트는 서로의 상태를 공유 할 수 있게 된다.

import { useState } from 'react';
import './App.css';
export default function App() {
  const [activeIndex, setActiveIndex] = useState(0); // 서로가 공유 가능한 state 

  return (
    <>
      <h1>Title 입니다</h1>
      <Panel
        // 현재 활성화 된 index 만 show 되도록 props 건내주기
        isActive={activeIndex === 0} 
        onShow={() => {
          // 각 컴포넌트 별 공유하는 setterfunction 을 이용해 state 변경 가능하도록 하기 
          setActiveIndex(0); 
        }}
      >
        나는 Panel 1입니다
      </Panel>
      <Panel
        isActive={activeIndex === 1}
        onShow={() => {
          setActiveIndex(1);
        }}
      >
        나는 Panel 2입니다
      </Panel>
    </>
  );
}

function Panel({ children, isActive, onShow }) {
  return (
    <div className='container'>
      {isActive ? <p>{children}</p> : <button onClick={onShow}>show</button>}
    </div>
  );
}

부모 컴포넌트는 하위 컴포넌트에게 서로가 공유 가능한 stateprops 로 건내주고

하위 컴포넌트들은 부모 컴포넌트의 state 를 변경 할 수 있는 setter functionprops 로 받아

부모 컴포넌트의 state 를 변경한다.

이렇게 변경된 statere-rendering 과정에서 하위 컴포넌트에게 재전달되며 렌더링을 새롭게 한다.

물론 서로가 공유 가능하게 하기 위해서 공유 불가능하기 전과의 state , setter function 로직이 변경되어야 한다.

Controlled and uncontrolled components

function Panel({ children }) {
  const [isActive, setIsActive] = useState(false); // <- local State 

  return (
    <div className='container'>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button
          onClick={() => {
            setIsActive(true);
          }}
        >
          show
        </button>
      )}
    </div>
  );
}

이전 예시처럼 컴포넌트 내부에 존재하는 state 들은 부모 컴포넌트나 다른 컴포넌트들이

상태를 변경 할 수 없는 컴포넌트는 uncontrolled component 라고 한다.

function Panel({ children, isActive, onShow }) {
  // 상위 컴포넌트로부터 상태에 따른 isActive 변수와 
  // setter function 을 담은 onShow 를 props 로 받음
  return (
    <div className='container'>
      {isActive ? <p>{children}</p> : <button onClick={onShow}>show</button>}
    </div>
  );
}

이처럼 부모 컴포넌트로부터 상위 렉시컬 환경의 state, setterFunctionprops 로 받는 컴포넌트를

Controlled Component 라고 한다.

컴포넌트는 상위 환경의 상태 변화에 따라 컨트롤 할 수 있기 때문이다.

UnControlled ComponentControlled Component 에 비해서 사용하기가 쉽고 재활용이 쉽다.

그 이유는 상위 환경이 어떻든과 상관 없이 본인만의 local state 를 가지고 있기 때문에

고려해야 할 것이 없기 때문이다.

Controlled ComponentUnControlled Component 에 비해서 고려해야 할 것이 많다.

상위 컴포넌트에서 propsstate 를 건내주어야 하기 때문이다.

하지만 고려할 점이 많다는 것은, 고려만 한다면 더욱 flexible 하게 사용이 가능하다는 것이다.

위 예시에서 보았듯 UnControlled Component 는 다른 컴포넌트와 교류가 안되기 때문에

본인만의 state 에 따른 로직만 처리하여 유연하지 못하다 .

물론 필요한 로직에 따라서는 UnControlled Component 를 사용하는게 맞을 때도 있다.
만약 위 예시에서 서로의 상태와 상관 없이 본인만의 상태에 따라 show 를 활성화 할 것이라면
UnControlled Component 로 하는 것이 훨씬 낫다.
본인 내부의 isActive state 만 관리하면 되기 때문이다.


정리

컴포넌트는 본인만의 state 에 따라 렌더링이 결정되는 UnControlled Component ,

다른 컴포넌트의 state 에 따라 렌더링이 결정되는 Controlled Component 가 존재한다.

Controlled Component 에 경우에는 상위 컴포넌트에게서 stateprops 로 전달 받아 사용한다.

profile
빨리 가는 유일한 방법은 제대로 가는 것이다

0개의 댓글