회고/Techit Frontend School 10기

[멋쟁이 사자처럼 프론트엔드 스쿨] 60일차 TIL - React Component, props, createElement, JSX(w. Babel, TypeScript)

kelly09 2024. 7. 28. 23:00

🍰 오늘도... vite보다 빠른 속도의 진도.

🍴 React Component

: 리액트 컴포넌트는 사용자 인터페이스(UI)의 뷰(view)를 구성하는 부품

  • 마크업으로 뿌릴 수 있는 JavaScript 함수
  • React 앱에서 모든 UI는 컴포넌트
  • 이름은 대문자로 시작
  • JSX 마크업을 반환

🍫 함수 컴포넌트

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

🍫 클래스 컴포넌트

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
    // this는 클래스 컴포넌트에서 컴포넌트의 인스턴스를 가리키기 위해 사용됨
    // 이 인스턴스는 해당 컴포넌트의 속성과 메서드 포함
  }
}

🍫 React.Component가 뭔데?

  • 자바스크립트 클래스로 정의된 React 컴포넌트의 기본 클래스
  • React 컴포넌트를 클래스로 정의하려면 내장 Component 클래스를 확장하고 render 메서드를 정의
import { Component } from 'react';

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

🍫 render()는 뭔데?

  • 클래스 컴포넌트에서 유일하게 필요한 메서드
  • 화면에 표시할 내용을 지정해야 함
  • render 메서드는 순수 함수로 작성해야 함
  • props, state 및 context가 동일한 경우 동일한 결과를 반환해야 함
  • 반환값: 유효한 모든 React 노드 반환 가능

🍫 그래서 왜 Component 클래스를 상속 받는데?

  • React의 기본 기능 사용 가능 : render 메서드 정의하고 사용할 수 있게 됨
  • React의 생명주기 메서드 사용 가능 : componentDidMount, componentDidUpdate, componentWillUnmount 등
  • state 관리 : this.state와 this.setState를 사용하여 컴포넌트 내부 상태 관리 가능
  • props 접근 : this.props를 통해 부모 컴포넌트로부터 전달 받은 속성들에 접근 가능
  • context 사용 : this.context를 통해 React의 Context API 사용 가능
  • 리렌더링 최적화 : shouldComponentUpdate 메서드를 구현하여 불필요한 리렌더링을 방지

🍫 클래스 컴포넌트에서 constructor()는 또 뭐야?

import React from 'react';
import ReactDOM from 'react-dom/client';

class ArchitectureList extends React.Component {
  constructor(props) {
    super(props); // 부모 클래스의 생성자를 호출, this.props를 초기화

    // 초기 상태 설정 (필요할 경우)
    this.state = {
      // 상태를 초기화하는 예시
      exampleState: 'initial state',
    };

    // 메서드를 바인딩하는 예시 (필요할 경우)
    // this.someMethod = this.someMethod.bind(this);
  }

  render() {
    // this.props로 전달된 count를 사용하여 리스트 아이템 생성
    const children = Array(this.props.count).fill(null).map((_, index) =>
      <li key={index}>{`${index + 1}01`}</li>
    );

    return (
      <ul id={this.props.id} className="architectures" lang="en">
        {children}
      </ul>
    );
  }
}

// ReactDOM.render 대신 createRoot 사용 (React 18+)
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);

// 컴포넌트에 prop 전달
root.render(<ArchitectureList id="architecture-list" count={5} />);
  • 컴포넌트를 초기화하는 특수한 메서드. 초기 상태 설정, 메서드 바인딩 등.
  • ex) this.state를 사용하여 컴포넌트 초기 상태 정의에 자주 사용됨.
  • 컴포넌트가 마운트되기 전에 호출됨.
  • super(props) 호출: constructor 내에서 this.props에 접근하려면 super(props)를 호출해야 함.
  • constructor에서 컴포넌트 인스턴스에 바인딩할 수 있음.

🍫 super(props)는 뭐야?

  • super - 부모 클래스의 생성자 호출에 사용됨. 
  • React 컴포넌트 맥락에서는 React.Component 클래스의 생성자를 호출함.
  • this.props에 접근 - props를 super에 전달함으로써 컴포넌트 인스턴스에서 this.props를 사용할 수 있게 함.

🍫 근데 props가 뭐지?😅

  • JSX 태그에 전달하는 정보
  • 읽기 전용 스냅샷임 - 렌더링 할 때마다 새로운 버전의 props를 받음
  • 변경할 수 없음 - 상호작용이 필요하면 state 설정
  • props를 전달하려면 JSX에 props를 추가
  • props를 읽을 땐 구조 분해 할당 문법 사용
  • size = 100 같이 기본값 지정 가능 - 누락/undefined인 props에 사용됨
  • props는 컴포넌트의 데이터를 처음에만 반영하는 게 아니라 모든 시점에 반영
export default function Profile() {
  return (
    <Avatar
      person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} 
      size={100} 
    />
  );
}
// person과 size가 props
  • 이렇게 하면 Avatar 코드 내에서 변수처럼 사용할 수 있음
function Avatar({ person, size }) { // 구조 분해 할당
  // person과 size는 이곳에서 사용 가능
}

// ---------------위 코드와 동일------------------ //
function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}
  • props 사용 시 부모 컴포넌트와 자식 컴포넌트를 독립적으로 생각할 수 있음
  • 인수와 동일한 역할!
  • props는 컴포넌트에 대한 유일한 인자
  • React 컴포넌트 함수는 하나의 인자인 props 객체를 받음
  • 보통은 전체 props 자체를 필요로 하지 않아서 개별 props로 구조 분해 할당

🍫 props를 구조 분해 할당을 통해 받는 게 이해가 안 가!

function Avatar({ person, size }) {
  // ...
}
// 위 코드는 아래 코드와 같아
function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}

// -----어떻게 같은 거야?------//

function Avatar(props) {
  const { person, size } = props;
  // ...
}
  • React가 이 컴포넌트를 렌더링 할 때, 하나의 props 객체를 전달함.
  • 함수 선언에서 중괄호를 사용하면, JavaScript는 이를 '이 함수는 객체를 인자로 받고, 그 객체에서 person과 size 속성을 추출하여 같은 이름의 변수로 만들겠다'라고 해석함.
  • 위 코드의 두 번째와 세 번째 코드의 차이점은 구조 분해가 함수의 매개변수 수준에서 일어난다는 것임.

🍫 컴포넌트 사용하기

// Welcome.js
import React from 'react';

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

export default Welcome;

// ------------------------------------------------------------------------------ //
// App.js
import React from 'react';
import Welcome from './Welcome'; // Welcome 컴포넌트를 임포트

function App() {
  return (
    <div>
      <Welcome name="Alice" />  {/* Welcome 컴포넌트를 사용하고 props 전달 */}
      <Welcome name="Bob" />
      <Welcome name="Charlie" />
    </div>
  );
}

export default App;
  • 컴포넌트를 한 번 정의한 뒤 원하는 곳에 원하는 만큼 사용할 수 있다는 게 큰 장점!
  • 컴포넌트 안에 다른 컴포넌트 정의 X
  • 자식 컴포넌트에 부모 컴포넌트 일부 데이터 필요한 경우 props로 전달

 

🍴 props

: 컴포넌트 속성(properties)은 컴포넌트를 다양하게 재사용 할 수 있게 함.

  • 읽기 전용임. 컴포넌트의 자체 props를 수정하면 안됨.
  • 자신의 props를 다룰 때 순수 함수처럼 동작해야 함.

🍫 순수 함수처럼 동작하라니?

function sum(a, b) {
  return a + b;
}
// 항상 동일한 입력값에 대해 동일한 결과를 반환함 => 순수 함수

function withdraw(account, amount) {
  account.total -= amount;
} 
// 자신의 입력값을 변경함 => 순수 함수 X

 

🍴 React.createElement

: React element 생성 가능. JSX를 작성하는 대신 사용할 수 있음.

const element = createElement(type, props, ...children)
  1. type: 생성할 요소의 유형. 유효한 React 컴포넌트. 
  2. props: 해당 요소에 전달할 속성을 포함하는 객체 또는 null. 
  3. children: 자식 요소들. 선택 사항. React element, 문자열, 숫자, 포탈, 빈 노드(null, undefined, true, false) 등.
import { createElement } from 'react';

function Greeting({ name }) {
  return createElement(
    'h1', // type
    { className: 'greeting' }, // props
    'Hello ', // children
    createElement('i', null, name), // children
    '. Welcome!'  children
  );
}
// --------------------JSX로 작성 시------------------------ //
function Greeting({ name }) {
  return (
    <h1 className="greeting">
      Hello <i>{name}</i>. Welcome!
    </h1>
  );
}

🍫 반환값

  • React element 객체 반환
  • type: 전달 받은 type
  • props: ref와 key를 제외한 전달 받은 props.
  • ref: 전달 받은 ref. 누락 시 null.
  • key: 전달 받은 key를 강제 변환한 문자열. 누락 시 null.

 

🍴 JSX(JavaScript XML)

: JavaScript를 확장한 문법. JavaScript 파일에서 HTML과 비슷한 마크업 작성할 수 있게 도와줌.

// 기본 문법
const element = <h1>Hello, world!</h1>;

// 표현식 삽입
const name = "Kelly";
const element = <h1>Hello, {name}</h1>

// 속성 정의 (camelCase)
const element = <div className="container">Content</div>

// 자식 요소 포함
const element = (
	<div>
      <h1>Title</h1>
      <p>Paragraph</p>
    </div>
);

// JSX 없이 React 사용
const element = React.createElement('h1', null, 'Hello, world!');
  • React element생성
  • HTML이 아니라 JavaScript이므로 예약어 사용에 주의
  • 모든 태그닫혀야 함
  • inline 스타일객체로 전달됨 ex. <div style={{color: 'red'}}>Text</div>

 

🍴 JSX 트랜스폼

: JSX는 브라우저가 직접 이해할 수 없는 문법이므로 JavaScript로 변환하는 과정이 필요함.

🍫 Babel

  • JavaScript 컴파일러.
  • TypeScript 코드의 transpile 작업도 지원함.

🍫 TypeScript 컴파일

  • TypeScript는 JavaScript의 상위 집합, 정적 타입 검사 기능을 추가함.
  • TypeScript 코드는 브라우저가 이해할 수 없으므로, JavaScript로 컴파일해야 함.
  • 이 작업은 TypeScript 컴파일러(tsc)를 통해 수행됨.

참고

https://ko.react.dev/

 

React

React is the library for web and native user interfaces. Build user interfaces out of individual pieces called components written in JavaScript. React is designed to let you seamlessly combine components written by independent people, teams, and organizati

ko.react.dev

https://ko.legacy.reactjs.org/docs/components-and-props.html#function-and-class-components

 

Components와 Props – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org