React - component와 props

haahi·2023년 2월 22일

React

목록 보기
2/6
post-thumbnail

이전에 component를 조금 살펴봤는데 이번에는 간단한 프로젝트를 만들어보면서 더 자세히 알아보고자 한다.

component

간단히 말하면 컴포넌트란 html을 반환하는 자바스크립트 함수라고 할 수 있다.

컴포넌트는 보통 기능이나 단위에 따라 각각의 파일로 분류를 하는데 이때 몇가지 규칙을 갖는다.

  1. 시작 문자는 대문자로 작성하며, 모든 단어가 하나로 이루어진다.
  2. 여러 단어가 모여서 만들어진 경우, 단어의 시작은 대문자로 한다.
  3. 파일명만 보고도 어떤 기능을 수행하는지 알 수 있어야 한다.

위 규칙으로 파일명(함수명)을 만들면 ExpenseItem 과 같이 만들 수 있다.
expense + item 두 단어를 합쳐서 만들었고, 함수명만 보고도 어떤 상품의 가격을 나타내는 기능을 하는구나 라고 추측을 할 수 있다.

function App() {
  return (
    <div>
      <h2>Let's get started!</h2>
      <div>This is React</div>
      <ExpenseItem />
    </div>
  );
}

이렇게 만들어진 컴포넌트는 위와같이 사용할 수 있다. 그런데 여기서도 약간의 규칙이 존재한다.

  1. 루트 요소는 단 1개만 반환되어야 한다.
  2. 사용자 지정 컴포넌트(ExpenseItem)과 달리 <div>, <h2> 같은 내장된 html은 소문자로 시작한다.

return 바로 하위에 있는 <div> 태그가 안에 있는 태그들을 감싸고 있는것이 보일 것 이다. 이처럼 반환되는 루트 요소는 1개만 가능하다.

컴포넌트들은 각각의 파일로 이루어져 있는데, A라는 파일에서 B라는 컴포넌트를 사용하고 싶을 수 있다. 이럴 때 사용하는 것이 export & import 이다.

export & import

먼저 내가 내보내고 싶은 컴포넌트 앞에 export를 사용한 뒤, 내보낸 컴포넌트를 사용하고 싶은 파일에서 import하면 컴포넌트를 사용할 수 있게 된다.

// componets/ExpenseItem.js
import "./ExpenseItem.css";

export default function ExpenseItem() {
  return (
    <div className="expense-item">
      <div>March 28th 2021</div>
      <div className="expense-item__description">
        <h2>Car Insurance</h2>
        <div className="expense-item__price">$294.97</div>
      </div>
    </div>
  );
}


// App.js
import ExpenseItem from "./components/ExpenseItem";

function App() {
  return (
    <div>
      <h2>Let's get started!</h2>
      <ExpenseItem />
    </div>
  );
}

export default App;

export된 ExpenseItem를 App.js에서 import하여 컴포넌트로 사용하였다.

props

props는 읽기 전용으로, 상위 컴포넌트에서 하위 컴포넌트에 값을 전달하기 위해 사용한다.

현재 작성한 컴포넌트들의 구조와 props는 위와 같이 이루어져 있다.
아래 코드를 통해 더 살펴보자.

// App.js
import Expenses from "./components/Expenses";

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>
      <Expenses items={expenses} />
    </div>
  );
}


// components/ExpenseDate.js
import "./ExpenseDate.css";

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

App.js 부터 받은 data를 props를 통해 전달 받아 ExpenseDate에서 사용하였다.

이렇게 props를 사용하면 아래와 같은 장점을 갖는다.

  1. 재사용 가능
  2. 다른 컴포넌트에서 해당 컴포넌트로 data 전달 가능

wrapper component

컴포넌트들을 감싸는 컴포넌트

ExpnesesExpenseItem 에서 공통으로 갖는 CSS 스타일을 분리하여 Card 컴포넌트를 만들었다.

// components/Card.js
import "./Card.css";

export default function Card(props) {
  const classes = "card " + props.className;

  return <div className={classes}>{props.children}</div>;
}
/* cmponents/Card.css */
.card {
  border-radius: 12px;
  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.25);
}

Expneses, ExpenseItem 에서도 갖는 스타일이 있기 때문에 card스타일과 함께 적용될 수 있도록 classes를 선언한 뒤 className에 넣어주었다.
{props.children} 은 Card 태그 사이에 오는 컴포넌트들을 보여주기 위해 사용하는 props이다.

이렇게 만들어진 wrapper component 는 아래 코드와 같이 사용되었다.

// components/ExpenseItem.js
import "./ExpenseItem.css";
import ExpenseDate from "./ExpenseDate";
import Card from "./Card";

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


// components/Expenses.js
import ExpenseItem from "./ExpenseItem";
import Card from "./Card";
import "./Expenses.css";

export default function Expenses(props) {
 return (
   <Card className="expenses">
     <ExpenseItem
       title={props.items[0].title}
       amount={props.items[0].amount}
       date={props.items[0].date}
     />
    				.
     				.
     				.
   </Card>
 );
}

React 페이지



0개의 댓글