ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React - 주요 개념 #4 Components 와 Props
    React 2020. 11. 27. 12:57

    컴포넌트를 통해 UI를 재사용 가능한 개별적인 여러 조각으로 나누고,

     

    각 조각을 개별적으로 살펴볼 수 있다. 

     


    개념적으로 컴포넌트는 Javascript 함수와 유사하다!

     

    props라는 임의의 데이터를 입력받은 후 화면에 어떻게 표시되는지를 기술하는 React element를 반환한다!

     

     

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

     

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

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

    이 함수는 데이터를 가진 하나의 props ( props는 속성을 나타내는 데이터) 객체인자를 받은 후 React 엘리먼트를 반환하므로

     

    유효한 React 컴포넌트이다! 이러한 컴포넌트는 Javscript 함수이기 때문에 말 그대로 함수 컴포넌트라고 부른다

     

     

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

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

    React의 관점에서 볼 때 위의 두 코드는 동일하다

     

    - but 뭔가 다른점이 있겠지..?

     

     

    컴포넌트 렌더링

    이전까지는 밑의 코드처럼 React element를 DOM으로 나타냈다.

    const element = <div />;
    

     

    React element는 사용자 정의 컴포넌트로도 나타낼 수 있따!

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

    React가 사용자 정의 컴포넌트로 작성한 element를 발견하면 JSX attribute와 자식을 

     

    해당 컴포넌트에 단일 객체로 전달한다! -> 이 객체를 props라고 부른다

     

     

    다음은 페이지에 "Hello, Sara"를 렌더링하는 코드이다.

    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }
    
    const element = <Welcome name="Sara" />;
    ReactDOM.render(
      element,
      document.getElementById('root')
    );

     

    주의

     - 컴포넌트 이름은 항상 대문자로 시작한다!!

     

     React는 소문자로 시작하는 컴포넌트를 DOM 태그로 처리한다. 예를 들어 <div />는 HTML의 div태그를 나타내지만

     

     <Welcome />은 컴포넌트를 나타내며 범위안에 Welcome이라는 사용자 정의 컴포넌트가 존재해야 한다.

     

     

    컴포넌트 합성

    컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할 수 있다.!!

     

    이는, 모든 세부 단계에서 동일한 추상 컴포넌트를 사용할 수 있음을 의미한다. React 앱에서는 버튼, 폼, 다이얼로그,

     

    화면 등의 모든 것들이 컴포넌트로 표현된다

     

    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }
    
    function App() {
      return (
        <div>
          <Welcome name="Sara" />
          <Welcome name="Cahal" />
          <Welcome name="Edite" />
        </div>
      );
    }
    
    ReactDOM.render(
      <App />,
      document.getElementById('root')
    );

    -> App component는 여러개의 Welcome component를 렌더링한다

     

     

    일반적으로 React 앱은 최상위에 단일 App Component를 가지고 있다. 하지만 기존 앱에 React를 통합하는 경우

     

    Button과 같은 작은 Component 부터 시작해서 뷰 계층의 상단으로 올라가면서 점진적으로 작업해야 할 수도 있다.

     

     

    Component 추출!

    컴포넌트를 여러개의 컴포넌트로 잘게 나눠보자!

    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>
      );
    }
    

    Comment Component는 author(객체), text(문자열), date(날짜)를 props로 받은 후 소셜 미디어 웹 사이트의 코멘트를 나타낸다.

     

    이 컴포넌트는 구성요소들이 전부 중첩으로 이루어져 있어서 변경하기 어려울 수 있고, 각 구성요소를 개별적으로 사용하기도

     

    힘들다. Comment Component에서 몇가지 Component를 추출해보자! 

     

     

    먼저 Avatar를 추출하자!

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

    Avatar Component는 자신이 Comment Component에서 렌더링 되는 것을 알필요가 없다!

     

    따라서, props의 이름을 author -> user 라는 더 일반적인 naming으로 변경! 

     

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

     

    function Comment(props) {
      return (
        <div className="Comment">
          <div className="UserInfo">
            <Avatar user={props.author} />
            <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>
      );
    }

    이렇게 나누면 일단 조금더 Comment Component가 간결해졌다

     

    다음으로 Avatar 옆에 사용자의 이름을 렌더링하는 UserInfo 컴포넌트를 추출해보자!

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

    이렇게 추출하면  Comment Component가 훨씬더 간단해졌다~~

    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>
      );
    }

     

    => 처음에는 Component를 추출하는 작업이 지루해 보일 수 있다..

     

     하지만 큰 볼륨의 프로젝트일 수록 재사용이 가능한 컴포넌트 단위로 분리해놓는 것은 절대 무시할 수 없다..

     

     UI 일부가 여러번 사용되거나(Button, Panel, Avatar), UI 일부가 복잡한 (App, FeedStory, Comment) 등은

     

     별도의 컴포넌트로 분리하는 것이 좋다

     

     

     

    props는 읽기 전용!!

    함수 컴포넌트, 클래스 컴포넌트 모두 컴포넌트 자체 props를 수정해서는 안된다.!!

     

    다음 sum 함수를 보자

    function sum(a, b) {
      return a + b;
    }

    이런 함수들을 순수 함수라고 부르는데 입력값을 바꾸려 하지 않고 항상 동일한 입력에 대해 동일한 출력을 반환하기 때문이다

     

    반면 밑의 함수는 순수함수가 아니다

    function withdraw(account, amount) {
      account.total -= amount;
    }

    왜? 자신의 입력값을 수정하기 때문에~

     

     

    => React는 유연하지만 한가지 엄격한 규칙이 있다.

     

         모든 React Component들은 자신의 props를 다룰때 순수함수처럼 동작해야한다!

     

     

    물론 애플리케이션 UI는 동적이며 시간에 따라 변합니다.

     

    이러한 상황을 해결하기 위해 state”라는 새로운 개념을 소개합니다.

     

    React 컴포넌트는 state를 통해 위 규칙을 위반하지 않고 사용자 액션, 네트워크 응답 및

     

    다른 요소에 대한 응답으로 시간에 따라 자신의 출력값을 변경할 수 있습니다.

    댓글

Designed by Tistory.