TIL.(React) Component와 Props - 8/3

예흠·2020년 8월 3일
0

wecode

목록 보기
22/43
post-custom-banner

1. Component

프론트앤드 개발에서 Component 라는 단어를 많이 사용합니다.
component(컴포넌트)란 재사용 가능한 UI 단위입니다.

동일 코드가 반복되는 부분을 하나의 component로 만들어서 같은 디자인의 input이 필요한 곳마다 재사용할 수가 있습니다.

컴포넌트를 하나만 만들고 여기저기서 재사용하면, input 디자인이 바꼈을 때 css 한줄만 수정하면 로그인, 회원가입, 내정보수정 페이지에 바뀐 디자인이 모두 반영될 것입니다.

컴포넌트는 독립적으로, 재사용가능한 코드로 관리할 수 있습니다.
하나의 컴포넌트에 필요한 html, css, js(validation check)를 모두 합쳐서 만들 수 있습니다.

컴포넌트는 함수랑 비슷합니다. 함수도 기능이 독립적이고 재사용할 수가 있죠? 그리고 컴포넌트도 input을 받아서 return 할 수 있습니다.
React 컴포넌트에서는 input을 props라고 말하고 return은 화면에 보여져야할 React요소가 return됩니다.

- Component 만들기

React는 Component를 만들고 관리하기 정말 좋은 라이브러리 입니다.
React에서는 컴포넌트를 class나 함수로 만들 수 있습니다.
어떤 때에는 함수로 만들면 좋고, 어떤 때에는 class로 만들어야만 합니다.
이제 컴포넌트를 어떻게 만들 수 있는지 알아봅시다.

1) 함수로 Component 구현하기

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

2) class로 Component 구현하기

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

class로 컴포넌트를 만드려면 React.Component 를 extend해서 생성합니다.
컴포넌트를 생성할 때 render() 메서드는 무조건 정의해야하고, return도 해주어야 합니다.
render() 메서드는 무조건 정의해야한다는 말은, component를 만들 때 필요한 메서드가 원래 더 있다는 말입니다. 그 중에서 render() 만 필수입니다.

- Component 사용

위처럼 정의한 컴포넌트는 함수/class 이름으로 사용할 수 있습니다.
태그처럼 <Welcome /> 으로 작성합니다.

우리가 정의한 컴포넌트를 사용할 때, 원하는 attribute를 얼마든지 추가할 수 있습니다.
그러면 Welcome 컴포넌트(함수)에서 parameter로 해당 attribute를 받아서 사용할 수 있습니다.
이것을 props라고 말합니다. props는 property의 줄임말입니다.
.(dot)으로 속성명에 접근가능하고, props.속성명 으로 속성 값을 가져올 수 있죠.

// 1. Welcome 컴포넌트 정의
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// 2. App 컴포넌트 정의
function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

// 3. 화면에 React 요소 그려주기
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

- 더 작은 Component로 분리하기

아래는 Comment라는 컴포넌트입니다.
컴포넌트는 재사용 가능한 코드 단위라고 했죠.
Comment 컴포넌트 내에도 더 재사용할 수 있는 요소들이 보이네요.

.avatar 요소를 컴포넌트로 만들겠습니다.
avatar 컴포넌트는 분명 댓글창 이외에도 사용자정보 등 여기저기 많이 쓰일 것 같습니다.

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

.avatar 부분을 그대로 떼와서 Avatar라는 이름으로 컴포넌트를 만들어줍니다.
Comment 컴포넌트에서는 props.author로 접근해서 avatarUrl과 name을 가져왔는데, Avatar 컴포넌트에서는 좀 더 직관적으로 사용할 수 있도록 user 라는 이름으로 받아오겠습니다.

props.user 에서 avatarUrl, name 값을 가져오도록 하겠습니다.
<Avatar />를 사용하는 측에서 user라는 attribute를 추가해야겠네요.

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

Avatar 컴포넌트에서 user의 avatarUrl과 name이 필요하므로, Comment 컴포넌트에서 props.author 정보를 user라는 attribute로 넘겨주었습니다.
props.author의 avatarUrl, name 값이 user를 통해 전달되었습니다.

function Comment(props) {
  return (
    <div className="comment">
      <div className="user-info">
        <Avatar user={props.author} /> //요기!!
        <div className="user-info-name">
          {props.author.name}
        </div>
      </div>
      <div className="comment-text">
        {props.text}
      </div>
      <div className="comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

한 번만 더 분리해보겠습니다! 이제는 .user-info 부분을 컴포넌트로 만들어볼까요.
재사용할 가능성이 1이라도 있다면 컴포넌트로 만들어주는 것이 좋습니다.
.user-info 부분을 그대로 떼어다가 UserInfo 라는 컴포넌트로 만들었습니다.

function UserInfo(props) {
  return (
    <div className="user-info">
      <Avatar user={props.user} />
      <div className="user-info-name">
        {props.user.name}
      </div>
    </div>
  );
}

Comment 컴포넌트는 아래처럼 확 간결해졌습니다!!

function Comment(props) {
  return (
    <div className="comment">
      <UserInfo user={props.author} />
      <div className="comment-text">
        {props.text}
      </div>
      <div className="comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}
profile
노래하는 개발자입니다.
post-custom-banner

0개의 댓글