JiSoo's Devlog

[Udemy React 완벽 가이드] Section 2 본문

Frontend/React

[Udemy React 완벽 가이드] Section 2

지숭숭숭 2024. 1. 4. 11:20

컴포넌트

  • 모든 사용자 인터페이스들은 결국 컴포넌트로 구성된다
  • 각각의 컴포넌트를 구축하고 리액트에게 최종 사용자 인터페이스에서 어떻게 구성할 것인지 명령할 수 있다
  • 리액트가 컴포넌트의 개념을 도입한 것은 재사용 가능하다는 점뿐만 아니라 우려사항들을 분리할 수 있기 때문이다
  • 대부분의 리액트 컴포넌트들은 HTML과 자바스크립트를 결합하는 것에 관한 것으로 물론 CSS도 추가하지만 그게 초점은 아님
  • 리액트는 HTML과 자바스크립트, CSS로 구성된 재사용 가능하고 반응하는 컴포넌트를 만들 수 있게 해준다
  • 리액트는 선언적 접근 방식을 사용한다
  • 최종 상태만 정의하고 어떤 상태를 사용해야 하는지만 정의한다
  • 모든 UI는 결국 여러 빌딩 블록(=컴포넌트)으로 구성되며, 따라서 사용자 인터페이스를 '컴포넌트의 조합'이라고 생각할 수 있다
  • 대상의 상태(UI)를 정의하면 해당 결과를 얻기 위해 어떤 JS 명령어를 실행해야 하는지를 React가 특정한다
  • 일반적으로 해당 컴포넌트가 사용될 때 화면에 표시되는 HTML(정확히는 JSX) 코드를 반환하는 JS 함수를 말한다

 

 

리액트 프로젝트 생성

  • npx create-react-app 새 프로젝트 생성
  • npm start 개발 서버 구동

 

 

표준 리액트 프로젝트 분석하기

  • index.js 파일에 있는 코드의 변형된 버전이 브라우저 실행 시 가장 먼저 실행된다
 
  • ReactDOM이라는 객체를 react-dom이라는 서드 파티 라이브러리에서 가져온다는 뜻으로 이렇게 가져와야 해당 라이브러리 기능을 index.js 파일에서 활용할 수 있다
 
 
 
  • './~~' 는 같은 폴더에 있는 파일

 

 

JSX

  • 자바스크립트 안에 있는 Html 코드로 자바스크립트 XML을 의미한다
  • 화면 뒷단에서 변환한다
  • React 프로젝트에서만 활성화되는 특수한 비표준 구문이다
 

 

 

리액트 작동 방식

  • 일반적인 자바스크립트에서 페이지에서 어떤 요소를 선택하려면 document.getElementById('root')를 입력해도 끝낸 것이 아니라 innerHTML=''를 설정해야 한다
  • 리액트에서는 최종 상태를 정의하기만 하면 화면에 불러오기 위한 지시사항들을 뒷담에 생성할 것이다

 

 

사용자 지정 컴포넌트 만들기

  • 리액트로 작업할 때 컴포넌트 트리를 만든다
  • App.js는 루트 컴포넌트로 index.js라는 시작 파일에서 렌더링되는 기본적인 컴포넌트
  • 리액트에 있는 컴포넌트는 단지 자바스크립트 함수일 뿐
  • 컴포넌트는 html 코드를 반환하는 함수
  • Html 코드를 러턴하는 함수인 컴포넌트를 생성해서 내보내고 사용하고 싶은 파일에서 임포트한다
ExpenseItem.js
 
App.js

JSX 코드 작성

  • JSX 코드에서 반환하는 문장마다 또는 JSX 코드 조각마다 반드시 한 개의 루트 요소를 갖는다
 

 

 

기본 CSS 스타일 추가

  • JSX 코드에서 클래스 이름을 추가하고 싶다면 자바스크립트에서처럼 class=""가 아니라 className="" 사용
 
 
 

 

 

JSX에서 동적 데이터 출력 및 표현식 작업

  • 컴포넌트를 쓰는 게 코드를 분산시킨다는 목적도 있지만 재사용 가능성도 중요한 목적
  • html 코드에서 고정된 값이 아니라 동적 위치 표시자를 이용한 값을 사용한다
 
  • 날짜는 날짜 객체이기 때문제 텍스트 형태로 출력 불가 -> toISOString() 호출해 날짜를 문자열로 출
 
 

 

"props"를 통해 데이터 전달하기

  • 컴포넌트 재사용
 
 
데이터가 컴포넌트에 고정되어 있어 같은 데이터만 재사용 가능
 
  • 속성을 추가해 데이터를 사용자 지정 컴포넌트에 전달 가능
  • 리액트는 우리가 컴포넌트로 사용하는 모든 컴포넌트에서 하나의 파라미터를 받도록 해준다
  • 리액트가 자동으로 전달한 키값 쌍을 props 객체에 받는데 키는 App에서 정의된 속성 이름(title, amount, date)
  • props 객체에서 접근하는 키는 우리가 선택한 속성 이름이어야 한다
  • 동적인 props를 위해 값을 설정할 때 중괄호 구문을 사용한다
  • props는 동적으로 설정된 값에만 국한되지 않는다
import ExpenseItem from "./components/ExpenseItem";

function App() {
  const expenses = [
    {
      id: "e1",
      title: "Toilet Paper",
      amount: 94.12,
      date: new Date(2020, 7, 14),
    },
    { id: "e2", title: "New TV", amount: 799.49, date: new Date(2021, 2, 12) },
    {
      id: "e3",
      title: "Car Insurance",
      amount: 294.67,
      date: new Date(2021, 2, 28),
    },
    {
      id: "e4",
      title: "New Desk (Wooden)",
      amount: 450,
      date: new Date(2021, 5, 12),
    },
  ];
  return (
    <div>
      <h2>Let's get started!</h2>
      <ExpenseItem
        title={expenses[0].title}
        amount={expenses[0].amount}
        date={expenses[0].date}
      ></ExpenseItem>
      <ExpenseItem
        title={expenses[1].title}
        amount={expenses[1].amount}
        date={expenses[1].date}
      ></ExpenseItem>
      <ExpenseItem
        title={expenses[2].title}
        amount={expenses[2].amount}
        date={expenses[2].date}
      ></ExpenseItem>
      <ExpenseItem
        title={expenses[3].title}
        amount={expenses[3].amount}
        date={expenses[3].date}
      ></ExpenseItem>
    </div>
  );
}

export default App;
 
import "./ExpenseItem.css";

function ExpenseItem(props) {
  return (
    <div className="expense-item">
      <div>{props.date.toISOString()}</div>
      <div className="expense-item__description">
        <h2>{props.title}</h2>
        <div className="expense-item__price">${props.amount}</div>
      </div>
    </div>
  );
}

export default ExpenseItem;
 
 

 

 

컴포넌트에 일반 JavaScript 논리 추가하기

  • props를 사용하는 목적은 컴포넌트를 자유롭게 설정하고 재사용할 수 있게 만들기 위해서 데이터를 컴포넌트에 전달하기 위해 사용
import "./ExpenseItem.css";

function ExpenseItem(props) {
  const month = props.date.toLocaleString("en-US", { month: "long" });
  const day = props.date.toLocaleString("en-US", { day: "2-digit" });
  const year = props.date.getFullYear();

  return (
    <div className="expense-item">
      <div>
        <div>{month}</div>
        <div>{year}</div>
        <div>{day}</div>
      </div>
      <div className="expense-item__description">
        <h2>{props.title}</h2>
        <div className="expense-item__price">${props.amount}</div>
      </div>
    </div>
  );
}

export default ExpenseItem;
 

 

컴포넌트를 여러 컴포넌트로 분할

  • 컴포넌트를 작고 집중적인 것으로 유지하는 것이 좋다
import "./ExpenseDate.css";

function ExpenseDate(props) {
  const month = props.date.toLocaleString("en-US", { month: "long" }); //도우미 상수
  const day = props.date.toLocaleString("en-US", { day: "2-digit" });
  const year = props.date.getFullYear();

  return (
    <div className="expense-date">
      <div className="expense-date__month">{month}</div>
      <div className="expense-date__year">{year}</div>
      <div className="expense-date__day">{day}</div>
    </div>
  );
}

export default ExpenseDate;
 
  • date 부분을 별도의 컴포넌트로 분리
  • 인자로 props 꼭 써줘야 함
  • App.js에서 date를 받을 때는 function의 인자로 props를 받아 전달받고 하위 컴포넌트인 ExpenseDate에 date를 넘겨줄 때는 저런 식으로 써줘야 함
 

 

컴포지션

  • 일반적으로 작은 구성요소부터 시작해 사용자 인터페이스를 구축하는 방식
  • 사용자 지정 컴포넌트를 일종의 컨텐츠를 감싸는 래퍼로 사용할 수 없다
  • css 파일에서 별도의 래퍼 컴포넌트로 일부 중복되는 코드를 추출할 수 있다
  • html 코드와 JSX 코드 <div>도 추출할 수 있다
  • 더 복잡한 JSX 구조를 가진 모달창이나 경고창같은 래퍼 컴포넌트를 보게 된다면 그런 경우에, 추출이 가능하다는 것은 수많은 코드의 중복을 피할 수 있게 해주고 다른 컴포넌트를 깔끔하게 유지할 수 있게 해준다
  • 컴포넌트를 결합할 때마다 우리는 합성을 이용하는 것이다
  • props.children은 래퍼 컴포넌트를 생성하게 하며 특별한 컴포넌트라고 할 수 있고 종종 필요하다
  • 이 특수한 children prop의 값은 항상 우리의 사용자 지정 컴포넌트의 시작 태그와 종료 태그 사이에 있는 콘텐츠가 된다
  • 만약 Card 컴포넌트에서 className을 설정하고 효과를 내도록 하기 위해서는 Card 컴포넌트에 const classes = ~~ 이렇게 넣어줘야 한다

 

** Card는 보통 둥근 모서리에 옅은 그림자와 같은 요소들이 있는 컨테이너 모양을 의미한다

 

Card.js

import "./Card.css";

function Card(props) {
  const classes = "card " + props.className; //card는 디폴트 클래스로 항상 적용된다, 밖에서 className으로 받는 것들은 문자열로 추가된다

  return <div className={classes}>{props.children}</div>; //children은 예약어
}

export default Card;

//재사용할 수 있는 래퍼 컴포넌트
 
 

 

 

JSX

  • 과거에는 항상 react를 임포트 했어야 했다
return React.createElement(
  'div',
  {},
  React.createElement('h2', {}, "Let's get started!"),
  React.createElement(Expenses, { items: expenses })
);
// JSX 코드의 대안
 
  • 복잡하고 번거로움
  • JSX 코드를 사용할 때 리액트가 사실은 내부에서 사용되고 있다는 것을 강조하기 위해 import React from "react"; 작성해 줌

 

 

대체 함수 문법

const App = () => {
 
const Expense = (props) => {
 
  • 화살표 함수 사용 (짧아서 추천)
728x90