[React] 기초 | Props의 정의 및 전달법

Re_Go·2024년 6월 3일
0

React

목록 보기
6/12
post-thumbnail
post-custom-banner

1. Props의 정의

props리액트 컴포넌트에 전달되는 데이터를 총칭합니다. 주로 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 사용(스페이스 리프팅)되는데요.

전달 된 props자식 쪽에서 수정을 할 수 없다는 특징을 가지고 있으며, 보통 전달 받는 쪽에서의 속성 이름은 props라고 사용을 합니다. (다른 이름으로도 지정 가능합니다.)

  1. index.jsx 컴포넌트 페이지
import './App.css'
import Viewer from "./components/Viewer"
import Controller from "./components/Controller"
import { useState } from "react"

function App() {

  const [count, setCount] = useState(0)
  const [input, setInput] = useState("")

  const onClickButton = (value) => {
    setCount(count + value);
  }

  return (
    <div className="App">
      <h1>Simple Counter</h1>
      <section><input value={input} onChange={(e) => {
        setInput(e.target.value)
      }} /></section>	
      <section><Controller onClickButton={onClickButton} /></section>
    </div>
  )
}
export default App

해당 코드는 간단한 Counter 앱인데요. 위의 코드에서는 Controller 섹션에서 컴포넌트 ControlleronClickButton 속성 이름과 onClickButton 메서드를 값으로 넘겨주고 있습니다.

  1. Controller.jsx 컴포넌트 페이지
import React from 'react'

export default function Controller({onClickButton}) {
  return (
    <div>
      <button onClick={() => {
        onClickButton(-1)
      }}>-1</button>
      <button onClick={() => {
        onClickButton(-10)
      }}>-10</button>
      <button onClick={() => {
        onClickButton(-100)
      }}>-100</button>
      <button onClick={() => {
        onClickButton(100)
      }}>+100</button>
      <button onClick={() => {
        onClickButton(10)
      }}>+10</button>
      <button onClick={() => {
        onClickButton(1)
      }}>+1</button>     
    </div>
  )
}

그리고 위의 코드인 Controller 컴포넌트 에서는 넘겨 받은 메서드가 각각의 버튼 컴포넌트의 onClick 이벤트 코드에 할당되어 들어갑니다.

2. props의 규칙

위의 코드는 분리된 두 컴포넌트 간에 부모 컴포넌트에서 자식 컴포넌트로의 데이터(속성) 이동을 표현한 예시인데요. 이러한 데이터 이동의 주체가 되는 props는 사용할 때 몇 가지 규칙을 가지고 있습니다.

- 속성은 읽기 전용입니다.

Controller 컴포넌트에서 onClickButton 함수를 props로 받았습니다. 이 함수는 부모 컴포넌트에서 전달되었으며, Controller 컴포넌트에서는 해당 함수를 호출하여 사용합니다. 하지만 Controller 컴포넌트에서는 이 함수를 변경할 수 없습니다. 이 함수는 읽기 전용입니다.

function Controller({ onClickButton }) {
  // onClickButton 함수는 읽기 전용이며, 변경할 수 없습니다.
  return <button onClick={onClickButton}>Click Me</button>;
}

- 속성을 사용하여 컴포넌트를 커스터마이징할 수 있습니다.

Controller 컴포넌트에서는 onClickButton 함수를 props로 받아 버튼 클릭 시 해당 함수를 호출합니다. 이를 통해 Controller 컴포넌트는 동적으로 버튼 클릭에 따라 동작을 변경할 수 있습니다.

function App() {
  // 특정 함수를 특정 컴포넌트에 전달
  const handleClick = () => {
    alert('Button clicked!');
  };
  return <Controller onClickButton={handleClick} />;
}

- 속성의 값을 변경하려면 부모 컴포넌트에서 변경해야 합니다.

onClickButton 함수는 App 컴포넌트에서 정의되고, Controller 컴포넌트로 props로 전달됩니다. onClickButton 함수 내부에서 상태를 변경하고 있지만, 상태를 변경하는 부분은 App 컴포넌트 내부에 있습니다. 이를 통해 속성(props)의 값을 변경할 때는 해당 Props를 전달하는 부모 컴포넌트에서 변경해야 합니다. (물론 useContext나 Redux와 같은 상태 관리 라이브러리를 활용하여 해결 가능합니다.)

// 예시 : Controller 컴포넌트는 onClickButton 함수를 제공 받지만, 해당 함수의 정의는 상태를 관리하는 컴포넌트에 위치해 있기 때문에, 함수를 전달 받아 이벤트가 발생 되어도 실제로는 해당 상태를 관리하는 부모 컴포넌트에서 상태가 변경됩니다.
function App() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <Controller onClickButton={handleClick} />
    </div>
  );
}

- 속성의 포함, 미포함은 선택적입니다.

Controller 컴포넌트에서는 onClickButton 함수를 필수 Props로 받았습니다. 그래서 Controller에서도 함수를 받기까지는 해야합니다. 하지만 다른 props를 받지 않는다면 해당 컴포넌트에서는 선택적으로 다른 props를 설정할 수 있습니다.

// 예시 : onClickButton은 제공받고 있으므로 반드시 받아줘야 하나
// label은 받고 있지 않으므로 Controller에서 임의로 정의해도 됩니다.
// 이럴 경우 label은 정의된 기본값으로서 사용 가능합니다.
function Controller({ onClickButton, label = 'Click Me' }) {
  return <button onClick={onClickButton}>{label}</button>;
}

- 속성 전달시 변수의 이름은 동일해야 합니다.

속성은 하나를 받든 속성을 받든 각각의 전달되는 속성의 이름이 일치해야 합니다. 단 순서는 일치하지 않아도 상관 없으며, 전달되는 매개속성의 이름과는 일치하지 않아도 됩니다.

// App 컴포넌트 : onClickButton이라는 이름으로 전달했다면
function App() {
  const handleClick = () => {
    console.log("Button clicked");
  };
  return (
    <Controller onClickButton={handleClick} label="Press Here" />
  );
}

// Controller 컴포넌트 : 받는 쪽에서의 함수 정의 또한 onClickButton 이여야 함 
function Controller({ onClickButton, label}) {
  return <button onClick={onClickButton}>{label}</button>;
}

- 속성 전달시 특정 속성 개수만 받을 수 있습니다.

속성을 전달 받을 때 특정 속성만 받을 수 있는데, 이 경우 나머지 개체들은 ``rest 연산자 (...rest)를 지정하여 객체 형태로 따로 받을 수 있는데, 만약 특정 개수를 받고 그 나머지에 대해서 지정해주지 않을 경우 해당 컴포넌트에 전달되지 않습니다.

function Controller({ onClickButton, ...rest }) {
  return <button onClick={onClickButton} {...rest}>Click Me</button>;
}

- 속성들을 단 하나의 개체로 받을 수도 있습니다.

여러 속성들을 하나의 개체로 전달 받을 때는 통칭 props 라고 네이밍을 하며(관례이지 강제는 아님), 이때 닷 노테이션(.)을 사용하여 전달 받은 값들 중 특정 값들에 접근 및 사용할 수 있습니다. (물론 props 라는 이름 말고 임의의 이름으로도 하나의 객체로 전달 받을 수 있습니다.)

function Controller(props) {
  return (
    <button onClick={props.onClickButton}>
      {props.label || 'Click Me'}
    </button>
  );
}

- 속성의 기본값을 지정할 수 있습니다.

속성이 제대로 전달되지 않은 경우에 대비하여 자식 컴포넌트 쪽에서 특정 속성의 기본값을 지정할 수 있습니다.

function Controller({ onClickButton, label = 'Default Label' }) {
  return (
    <button onClick={onClickButton}>{label}</button>
  );
}

- 하위 컴포넌트 및 요소를 Children 속성으로 받을 수 있습니다.

특정 컴포넌트의 하위 컴포넌트에 정보를 전달할 때, 굳이 직접적으로 전달하지 않아도 전달하고자 하는 대상 컴포넌트의 하위 부분에 변수나 객체, 컴포넌트를 포함시키면 받는 쪽에서는 children 이라는 리액트가 제공하는 고유 속성으로 전달받아 활용할 수 있습니다.

// App.jsx에서 Controller 안에 Greeting과 Saying 변수를 포함시키면
function App() {
  const messages = {
    greeting: "안녕하세요.",
    saying: "카운터 앱입니다."
  };

  const handleClick = () => {
    console.log("Button clicked");
  };

  return (
    <Controller onClickButton={handleClick}>
      {messages}
    </Controller>
  );
}

// Controller 컴포넌트에서는 children라는 이름을 이용해 포함된 요소 및 컴포넌트들을 받아서 활용할 수 있습니다.
function Controller({ onClickButton, children }) {
  return (
    <button onClick={onClickButton}>
      {children.greeting} {/* 객체의 greeting 속성 사용 */}
      {children.saying} {/* 객체의 saying 속성 사용 */}
    </button>
  );
}

- HTML의 기본 태그의 고유 속성들을 지원합니다.

리액트 에서는 모든 컴포넌트의 return문 안에서 표현된 html 고유 태그들의 속성들인 onClick, onChange 등의 기능을 지원합니다. 이는 커스텀 컴포넌트의 속성들은 리액트에서의 전달 속성만을 담당하는 것과 대비됩니다.

// 상위 컴포넌트 (ButtonComponent)
function ButtonComponent() {
  const handleClick = () => {
    alert('Button clicked!');
  };

  return (
    <div>
      {/* 
        1. HTML 고유 태그인 <button> 요소에 onClick을 설정하면,
           해당 태그가 브라우저의 기본 이벤트 핸들러 시스템에 의해 
           즉시 처리되어, handleClick 함수가 바로 발동됩니다.

        2. 반면, 커스텀 컴포넌트인 <Button>에 onClick을 설정하려면,
           Button 컴포넌트에서 onClick이라는 이름의 prop을 받아야 합니다.
           커스텀 컴포넌트는 HTML 요소와 달리, 직접적으로 이벤트 핸들러를 
           처리하지 않으므로, props를 통해 함수가 전달되고,
           내부에서 해당 함수를 처리해주어야 handleClick이 발동됩니다.
      */}
      <button onClick={handleClick}>Click me!</button>
      <Button onClick={handleClick}>Click me?</Button>
    </div>
  );
}

// Button 컴포넌트
function Button({ onClick, children }) {
  return <button onClick={onClick}>{children}</button>;
}
profile
인생은 본인의 삶을 곱씹어보는 R과 타인의 삶을 배워 나아가는 L의 연속이다.
post-custom-banner

0개의 댓글