본문 바로가기
Software/JS & TS & React

전역변수 없이 속성으로 자식 컴포넌트에 데이터 전달하기

by lovey25 2023. 2. 27.
반응형

전역변수를 사용하지 않고 컴포넌트 속성으로 데이터를 자식 컴포넌트로 전달하는 방법입니다.

다음과 같은 예가 있습니다. 드롭다운에서 선택한 값에 따라서 하위 컴포넌트가 변경됩니다. 

이런 기능을 구현하는 방법은 가장 먼저 떠오르는 것이 드롭다운의 선택값을 저장하는 변수를 useState로 정의하고 이 값의 변화에 따라 랜더링 되는 컴포넌트를 구별해서 작성하는 겁니다.

import { useState } from "react";

const Result = ({ type }) => {
  return <div>{type}</div>;
};

export default function App() {
  const [state, setState] = useState("");
  const Type = () => {
    return (
      <div>
        선택:
        <select onChange={(e) => setState(e.target.value)} value={state}>
          <option value="type-1">이건 타입 1번</option>
          <option value="type-2">이건 타입 2번</option>
        </select>
      </div>
    );
  };
  return (
    <>
      <Type / >
      <Result type={state} />
    </>
  );
}

 

여기서는 <Type>, <Result> 두 가지 컴포넌트가 사용되고 있습니다. <Type>은 드롭다운 인터페이스를 제공하고 <Result>는 인자로 넘겨받은 문자를 화면에 표시해 주는 역할을 합니다. 그런데 만약 <Result>를 <Type> 컴포넌트의 자식 컴포넌트로 해서 외부의 useState 변수를 사용하지 않고 독립적으로 동작하는 컴포넌트를 만들어야 할 필요를 생각해 보겠습니다.

"state"라는 변수는 다른 곳에서는 사용하지 않고 <Type> 이하에서만 사용한다고 가정하면 useState 선언은 위 코드처럼 <App> 컴포넌트에서 선언할게 아니라 <Type>에서 하는 게 맞을 것 같습니다. 더불어 "state"가 변경될 때마다 다시 랜더링 되는 컴포넌트도 <Type> 이하로 한정되기 때문에 효율적이겠죠.

그렇다면 이제 문제는 <Type> 컴포넌트에서 선택한 타입을 자식 컴포넌트인 <Result>로 전달하는 방법인데 함수가 그렇든 인자로 넘겨주면 될 것 같은데 리액트에서는 그 방법이 확 와닿지 않았는데 다음과 같이 하면 됩니다. <App>, <Type>, <Result> 컴포넌트가 서로 의존하지 않고 완전히 독립하고 있습니다.

import { useState } from "react";

const Type = (props) => {
  const [state, setState] = useState("");

  return (
    <div>
      선택:
      <select onChange={(e) => setState(e.target.value)} value={state}>
        <option value="type-1">이건 타입 1번</option>
        <option value="type-2">이건 타입 2번</option>
      </select>
      <div>{props.children(state)}</div>
    </div>
  );
};

const Result = ({ type }) => {
  return <div>{type}</div>;
};

export default function App() {
  return (
    <>
      <Type>{(opt) => <Result type={opt} />}</Type>
    </>
  );
}

<Type> 컴포넌트는 드롭다운 인터페이스를 제공하고 사용자가 선택한 결과를 컴포넌트 내부 변수인 "state"에 저장합니다. 그런데 <Type>을 호출할 때 인자로 <Result> 컴포넌트를 같이 넘겨주고 있습니다. 그래서 <Type>에서는 컴포넌트를 반환할 때 인자 중 ".children()"을 활용하는데 이때 사용자가 선택한 "state"변수를 같이 전달합니다. 그러면 마지막으로 <Result> 컴포넌트는 인자로 받은 "state"값을 출력하게 됩니다.

여기서 핵심은 ".children()"인데 리액트 컴포넌트의 모든 자식 컴포넌트라고 이해하면 될 것 같습니다. 랩핑이라는 개념과도 관련이 있는 것 같은데, 여기서는 <Type> 컴포넌트를 호출하는 태그 "<Type>, </Type>"사이에 있는 모든 내용이 해당되고 이때 매개변수 "opt"를 사용했는데 이 매개변수를 통해서 "state"가 흘러들어 가는 거죠.

첨에 이게 무슨 코드인가 도무지 이해가 되지 않아서 정리를 시작했는데 글을 쓰고 있는 지금도 내가 무슨 말을 하는 건가 싶네요. 컴포넌트들이 꼬리에 꼬리를 물고 있는 듯한 게 혼란스럽네요.

 

끝!

반응형

댓글