(React) Components & Props

호두파파·2021년 4월 12일
0

React

목록 보기
16/38
post-thumbnail

개념적으로 컴포넌트는 JavaScript 함수와 유사하다. "props"라고 하는 임의의 입력을 받은 후, 화면에 어떻게 표시되는지를 나타내는 React 엘리먼트를 반환합니다.

함수 컴포넌트와 클래스 컴포넌트

컴포넌트를 정의하는 가장 간단한 방법은 JavaScript 함수를 작성하는 것이다.

function Welcom(props) {
  return <h1>Hello, {props.name}</h1>;
}

이 함수를 데이터를 가진 하나의 "props"(props는 속성을 나타내는 데이터이다.) 객체 인자를 받은 후 React 엘리먼트를 반환하므로 유효한 React 컴포넌트이다. 이러한 컴포넌트는 JavaScript 함수이기 때문에 말 그대로 "함수 컴포넌트"라고 호칭한다.

또한 ES6 class를 사용해 컴포넌트를 정의할 수 있다.

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}
  </h1>;
  }
}

React 컴포넌트
컴포넌트는 개념적으로 props를 input으로 하고 UI가 어떻게 보여야 하는지 정의하는 React Element를 output하는 함수이다.
따라서 합성을 이용하여 "UI를 재사용할 수 있고 독립적인 단위로 쪼개어 생각"할 수 있게 한다.

컴포넌트는 각 프로세스가 진행될 때에 따라 Lifecycle 함수로 불리는 특별한 함수가 실행된다. 개발자는 이를 재정의해 컴포넌트를 제어한다.

컴포넌트 렌더링

이전까지는 React 엘리먼트를 DOM태그로 나타냈지만,

const element = <div />;

사용자 정의 컴포넌트로도 나타낼 수 있다.

const element = <Welcome name="Sara" />;

React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하면 JSX 어트리트뷰와 자식을 해당 컴포넌트에 단일 객체로 전달한다. 이 객체를 "props"라고 한다.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
  element, 
  document.getElementById('root')
);
// 1. <Welcome name="Sara" /> 엘리먼트로 ReactDOM.render()를 호출한다.
// 2. React는 {name: "Sara"}를 props로 하여 Welcome 컴포넌트를 호출한다.
// 3. Welcome 컴포넌트는 결과적으로 <h1>Hello, Sara</h1> 엘리먼트를 반환한다.
// 4. ReactDOM은 <h1>Hello, Sara</h1> 엘리먼트와 일치하도록 DOM을 효율적으로 업데이트 합니다. 
// ❗️주의. 컴포넌트의 이름은 항상 대문자로 시작해야 한다. 

컴포넌트 합성

컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할 수 있다. 이는 모든 세부 단계에서 동일한 추성 컴포넌트를 사용할 수 있음을 의미한다. React 앱에서는 버튼, 폼, 다이얼로그, 화면 등의 모든 것들이 흔히 컴포넌트로 표현된다.

function Welcome(props) {
  return <h1>Hello, {prop.name}</h1>
}

fuction App() {
  return (
    <div>
      <Welcome name="Hodoo" />
      <Welcome name="Wero" />
      <Welcome name="Bao" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

일반적으로 새 React 앱은 최상위에 단일 App 컴포넌트를 가지고 있다. 하지만 기존 앱에 React를 통합하는 경우에는 Button과 같은 작은 컴포넌트부터 시작해서 뷰 계층의 상단으로 올라가면서 점진적으로 작업해야 할 수 있다.

컴포넌트 추출

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

이 컴포넌트는 구성요소들이 모두 중첩 구조로 이루어져 있어서 변경하기 어려울 수 있다. 각 구성요소를 개별적으로 재사용하기도 힘든 구조다. 그래서 컴포넌트를 추출해서 분리하는 작업이 필요하다.

function Avatar(props) {
  return (
     <img className="Avatar"
       src={props.author.avatarUrl}
       alt={props.author.name}
     />
  );
}

Avatar는 자신이 Commnet 내에서 렌더링 된다는 것을 알 필요가 없다. 따라서 props의 이름을 author에서 더욱 일반화된 user로 변경했다.

props의 이름은 사용될 context가 아닌 컴포넌트 자체의 관점에서 짓는 것을 권장한다.

재사용 가능한 컴포넌트를 만들어 놓는 것은 더 큰 앱에서 작업할 때 두각을 나타낸다. UI일부가 여러번 사용되거나(Button, Panel, Avatar), UI일부가 자체적으로 복잡한(App, FeedStory, Comment) 경우에는 별도의 컴포넌트로 만드는 것이 좋다.

props는 읽기 전용

함수 컴포넌트나 클래스 컴포넌트 모두 컴포넌트의 자체 props를 수정해서는 안된다.
모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수처럼 동작해야 한다.

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글