ReactNextCentral

컴포넌트에 Props 전달

Published on
이 글은 리액트 컴포넌트에서 props를 전달하고 활용하는 방법에 대한 설명을 포함하고 있습니다.
Table of Contents

리액트 컴포넌트는 서로 통신하기 위해 props를 사용합니다. 부모 컴포넌트는 자식 컴포넌트에 props를 제공하여 정보를 전달할 수 있습니다. Props는 HTML 속성을 생각나게 할 수도 있지만, 객체, 배열 및 함수와 같은 모든 JavaScript 값으로 props를 통해 전달할 수 있습니다.

익숙한 props

props는 JSX 태그에 전달하는 정보입니다. 예를 들어, className, src, alt, width, height는 <img>에 전달할 수 있는 일부 props입니다.

Edit silly-moon-2nuz15

<img> 태그에 전달할 수 있는 props는 미리 정의되어 있습니다 (리액트DOM은 HTML 표준을 준수합니다). 하지만 <Avatar>와 같이 직접 만든 컴포넌트에도 다양한 props를 전달할 수 있습니다. 다음은 그 방법입니다!

컴포넌트에 props 전달하기

다음 코드에서 Profile 컴포넌트는 자식 컴포넌트인 Avatar에 어떤 props도 전달하지 않고 있습니다.

export default function Profile() {
  return (
    <Avatar />
  );
}

Avatar에 일부 props를 전달할 수 있습니다.

단계 1: 자식 컴포넌트에 props 전달하기

먼저, Avatar에 일부 props를 전달하세요. 예를 들어, person (객체)size (숫자)라는 두 가지 props를 전달해 보겠습니다.

export default function Profile() {
  return (
    <Avatar
      person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
      size={100}
    />
  );
}

참고 person= 다음의 이중 중괄호가 혼란스럽다면, 그저 JSX 중괄호 내의 객체일 뿐임을 상기하세요.

이제 Avatar 컴포넌트 내에서 이러한 props를 읽을 수 있습니다.

단계 2: 자식 컴포넌트 내에서 props 읽기

person, size와 같은 이름을 콤마로 구분하여 ({}) 바로 다음의 function Avatar 뒤에 나열하여 이러한 props를 읽을 수 있습니다. 이를 통해 변수처럼 Avatar 코드 내에서 사용할 수 있습니다.

function Avatar({ person, size }) {
  // person과 size를 이곳에서 사용할 수 있습니다
}

person과 size props를 사용하여 렌더링하는 데 필요한 로직을 Avatar에 추가하면 됩니다.

이제 다양한 props로 Avatar를 다양한 방식으로 렌더링할 수 있습니다. 값을 조정해 보세요!

Edit immutable-hill-1l09cq

Props를 사용하면 부모와 자식 컴포넌트를 독립적으로 생각할 수 있습니다. 예를 들어, Profile 내에서 person 또는 size props를 변경하더라도 Avatar가 이를 사용하는 방식을 생각할 필요가 없습니다. 마찬가지로, Avatar가 이러한 props를 사용하는 방법을 변경할 수 있으며 Profile을 확인하지 않아도 됩니다.

Props를 "버튼"으로 생각할 수 있습니다. 함수의 인수와 마찬가지로, props는 컴포넌트의 유일한 인수입니다! 리액트 컴포넌트 함수는 단일 인수, 즉 props 객체를 허용합니다.

function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}

일반적으로 전체 props 객체 자체가 필요하지 않기 때문에 개별적인 props로 분해합니다.

props를 선언할 때 () 사이에 있는 {} 중괄호 쌍을 놓치지 마세요.

function Avatar(
    { person, size }) {
  // ...
}

이 구문은 해체 할당이라고 하며, 함수 매개변수에서 속성을 읽는 것과 동일합니다.

function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}

props에 기본값 지정하기

값이 지정되지 않았을 때 기본값을 props에 지정하려면, 파라미터 바로 뒤에 =와 기본값을 넣는 해체 할당을 사용할 수 있습니다.

function Avatar({ person, size = 100 }) {
  // ...
}

이제 size prop이 없이 <Avatar person={...} />로 렌더링되면 size는 100으로 설정됩니다.

기본값은 size prop이 누락되었거나 size={undefined}로 전달된 경우에만 사용됩니다. 그러나 size={null} 또는 size={0}과 같이 전달하는 경우 기본값은 사용되지 않습니다.

JSX 스프레드 구문을 사용하여 props 전달하기

가끔씩 props를 전달하는 것이 매우 반복적일 수 있습니다.

function Profile({ person, size, isSepia, thickBorder }) {
  return (
    <div className="card">
      <Avatar
        person={person}
        size={size}
        isSepia={isSepia}
        thickBorder={thickBorder}
      />
    </div>
  );
}

반복적인 코드는 문제가 없습니다. 가독성이 좋을 수도 있습니다. 그러나 때로는 간결함을 더 중요시할 수 있습니다. 일부 컴포넌트는 Avatar와 같이 모든 props를 자식 컴포넌트로 전달합니다. 그들은 직접 props 중 하나도 사용하지 않기 때문에 더 간결한 "스프레드" 구문을 사용하는 것이 의미가 있을 수 있습니다.

function Profile(props) {
  return (
    <div className="card">
      <Avatar {...props} />
    </div>
  );
}

이렇게 하면 Profile의 모든 props가 개별적으로 나열되지 않고도 Avatar에 모두 전달됩니다.

스프레드 구문을 사용할 때는 분별하여 사용하세요. 거의 모든 컴포넌트에서 사용하고 있다면 문제가 있을 수 있습니다. 종종 컴포넌트를 분할하고 자식을 JSX로 전달해야 하는지 확인해야 합니다. 이에 대해서는 곧 자세히 알아보겠습니다!

자식으로 JSX 전달하기

내장된 브라우저 태그를 중첩하는 것이 일반적입니다.

<div>
  <img />
</div>

자체 컴포넌트도 동일한 방식으로 중첩할 때가 있습니다.

<Card>
  <Avatar />
</Card>

JSX 태그 내에 콘텐츠를 중첩할 때, 부모 컴포넌트는 해당 콘텐츠를 children이라는 prop으로 수신합니다. 예를 들어, 아래의 Card 컴포넌트는 children prop으로 <Avatar />를 받아서 래퍼 div 안에서 렌더링합니다.

Edit clever-herschel-e3k6xg

<Avatar><Card> 안에 있는 일부 텍스트로 바꿔보면 Card 컴포넌트가 중첩된 콘텐츠를 어떻게 감쌀 수 있는지 확인할 수 있습니다. Card는 그 안에 렌더링되는 내용을 "알 필요"가 없습니다. 이 유연한 패턴은 많은 곳에서 볼 수 있습니다.

컴포넌트에 children prop이 있는 것은 부모 컴포넌트에 의해 임의의 JSX로 "채워질 수 있는" "빈 공간"이 있는 것으로 생각할 수 있습니다. 일반적으로 children prop을 시각적인 래퍼 (패널, 그리드 등)에 사용합니다.

props가 시간에 따라 어떻게 변경되는지

아래의 Clock 컴포넌트는 부모 컴포넌트로부터 두 가지 props를 받습니다. color와 time (부모 컴포넌트의 코드는 생략되었습니다. 이 코드는 상태를 사용하며, 현재는 자세히 설명하지 않을 예정입니다.)

아래의 선택 상자에서 색상을 변경해 보세요:

Edit brave-bardeen-k30nx2

이 예제는 컴포넌트가 시간이 지남에 따라 다른 props를 받을 수 있다는 것을 보여줍니다. Props는 항상 정적이지 않습니다! 여기에서는 time prop이 1초마다 변경되고, color prop은 다른 색상을 선택할 때 변경됩니다. Props는 단지 컴포넌트의 데이터를 나타내는 것뿐만 아니라 어느 시점에서든 컴포넌트의 데이터를 반영합니다.

그러나 props는 변경할 수 없는 불변이라는 컴퓨터 과학 용어입니다. 컴포넌트가 props를 변경해야 하는 경우 (예: 사용자 상호 작용 또는 새 데이터에 대한 응답으로) 부모 컴포넌트에게 다른 props (새 객체)를 전달해야 합니다! 그리고 예전 props는 버려지고, 결국 JavaScript 엔진이 그들이 사용한 메모리를 회수할 것입니다.

props를 "변경하려고 하지 마세요". 사용자 입력에 대응해야 할 때 (예: 선택한 색상 변경) props를 "설정"해야 합니다. 이에 대해서는 상태: 컴포넌트의 메모리에서 알아보실 수 있습니다.

요약

  • props를 전달하려면 HTML 속성과 마찬가지로 JSX에 추가합니다.
  • props를 읽으려면 function Avatar({ person, size }) 해체 구문을 사용합니다.
  • 누락된 및 undefined props에 대한 기본값으로 size = 100과 같이 기본값을 지정할 수 있습니다.
  • JSX 스프레드 구문인 <Avatar {...props} />를 사용하여 모든 props를 전달할 수 있지만, 과용하지 않도록 주의하세요!
  • <Card><Avatar /></Card>와 같이 중첩된 JSX는 Card 컴포넌트의 children prop으로 나타납니다.
  • Props는 시간에 따라 변경됩니다. 각 렌더링은 새로운 버전의 props를 받습니다.
  • props를 "변경하려고"하지 마세요. 사용자 상호 작용에 응답해야 할 때는 "상태를 설정"해야 합니다.