컴포넌트
모든 사용자 인터페이스는 컴포넌트로 구성되어 있습니다.
HTML, CSS, JavaScript가 조합된 컴포넌트를 합쳐서 전체를 만들어냅니다.
컴포넌트를 사용하면 재사용성, 구성요소의 분산(코드 베이스를 작게, 관리하기 편함)의 이점이 있습니다.
특징
리액트 코드는 선언적 방식으로 작성됩니다.
리액트는 컴포넌트를 만들기 위해 선언형 접근법을 사용합니다.
이것은 자바스크립트처럼 DOM 명령을 직접 작성할 필요가 없고 원하는 최종 상태만 정의하는 방법입니다.
원하는 최종 상태만 알려주면 리액트가 배후에서 전부 처리해줍니다.
앱을 많은 컴포넌트로 분해합니다.
컴포넌트 트리가 만들어집니다.
최상단에 있는 컴포넌트만 ReactDOM의 render( ) 명령을 받아 HTML 페이지에 직접 렌더링 됩니다.
다른 컴포넌트들은 HTML의 요소로 이용됩니다.
한 컴포넌트에 루트 요소가 하나만 있어야 합니다.
return(
<div>
<div></div>
</div>
);
// 최상단 요소가 한 개 (O)
return(
<div></div>
<div></div>
);
// 최상단 요소가 두 개 (X)
왜 리턴 요소는 최상단 한 개만 가능할까요?
리액트 프로젝트를 보면 react와 react-dom 의존성을 확인할 수 있습니다.
최신의 프로젝트들을 보면 react-dom을 사용하는 모습을 볼 수 있지만 (index.js 같은 파일) react는 어디에서 import 되지 않는 것 같습니다.
예전에는 JSX를 사용하려면 모든 파일에 import를 했어야 했습니다.
그렇다면 JSX를 안쓰던 react는 어떤 식으로 리턴을 했을까요?
//return (
// <div>
// <h2>Let's get started!</h2>
// <Expenses items={expenses} />
// </div>
//);
return React.createElement(
'div',
{},
React.createElement('h2', {}, 'Let\'s get started!'),
React.createElement(Expenses, {items: expenses}); //Expenses는 import된 컴포넌트, 세 번째 인수는 없으므로 생략
);
이런식으로 직접 요소들을 만든 것을 리턴해줬습니다.
현재의 JSX를 사용해도 결국에는 이 메서드가 자동 생성되어 호출됩니다.
이 메서드에는 세 개의 인수를 넣어줘야 합니다.
1. div, h2 .. 와 같이 만들어야 하는 요소
2. 요소의 모든 속성을 설정하는 객체
3. 시작 및 종료 태그 사이에 들어갈 콘텐츠 ( 무한히 긴 인수 리스트를 넣을 수 있다.)
이 코드는 JSX 코드에 비해 읽기 힘들고 번거롭습니다. 하지만 웹으로 가기 전의 자바스크립트가 이렇게 변환된다는 것을 알게 된다면 왜 React를 import 해야했고, 왜 나란히 있는 요소를 리턴할 수 없는지 알 수 있습니다.
리턴 값이 React.createElement( ) React.createElement( ) 이런 식으로 두 개 이상이 되기 때문입니다.
배열로 리턴할 수 없었던걸까?
요소의 배열은 안되는 것 같습니다.
JSX (JavaScript XML)
JSX는 간단히 말해 자바스크립트 안에 있는 HTML 코드입니다.
원본 js 코드는 브라우저 개발자 도구 -> sources에서 확인해 볼 수 있습니다.
JSX에서 동적 데이터 출력하기 및 표현식 작업하기
JSX에서도 자바스크립트 코드와 표현식을 사용할 수 있습니다.
import './ExpenseItem.css';
function ExpenseItem() {
const expenseDate = new Date(2023, 8, 01);
const expenseTitle = '자동차 보험';
const expenseAmount = 200,000;
return (
<div className="expense-item">
<div>{expenseDate.toISOString()}</div>
<div className='expense-item__description'>
<h2>{expenseTitle}</h2>
<div className='expense-item__price'>₩{expenseAmount}</div>
</div>
</div>
);
}
export default ExpenseItem;
props를 통해 데이터 전달하기
컴포넌트는 기본적으로 다른 컴포넌트 안의 데이터를 사용할 수 없습니다.
그렇지만 props (properties) 를 이용하여 사용자 지정 컴포넌트에 데이터를 전달할 수 있습니다.
다음과 같이 속성을 추가하여 데이터를 전달합니다.
다음과 같은 절차를 따릅니다.
- App 에 가져온 사용자 지정 컴포넌트를 <importedJS /> 라 합시다.
- <importedJS title={ } date={ } price={ } /> 이와 같이 속성처럼 사용하여 객체의 key, value 값을 넘겨줍니다. (key값은 마음대로 정해도 됩니다. 다만 불러올 때 정해준 키 이름으로 불러와야 합니다.)
- importedJS 컴포넌트에서 props 매개변수를 만들고 해당 값을 표현해줍니다.
//importedJS의 function 부분
function 함수이름 (props) {
return(
<div>
<h1>{props.title}</h1>
<h1>{props.date.toISOSting()}</h1>
<h1>{props.price}</h1>
</div>
);
}
매개변수 props를 구조분해할당으로 대신할 수 있습니다.
function 함수이름 ({date title, amount}) {
return(
<div>
<h1>{title}</h1>
<h1>{date.toISOSting()}</h1>
<h1>{price}</h1>
</div>
);
}
만약 App 부분에서 객체 형태로 데이터를 전달했다면 다음과 같이 표현할 수 있습니다.
// App에서 배열 형태의 객체를
// <importedJS items = {객체이름} /> 으로 전달했다면
function 함수이름 (props) {
return(
<div>
<h1>{props.객체이름[0].title}</h1>
<h1>{props.객체이름[0].date.toISOSting()}</h1>
<h1>{props.객체이름[0].price}</h1>
</div>
<div>
<h1>{props.객체이름[1].title}</h1>
<h1>{props.객체이름[1].date.toISOSting()}</h1>
<h1>{props.객체이름[1].price}</h1>
</div>
);
}
컴포지션 (자식 props)
다른 모든 종류의 컨텐츠를 감싸는 컴포넌트를 만들고 싶을 때 사용하는 개념입니다.
{props.children} 으로 사용할 수 있으며 children은 예약어입니다. 그렇기 때문에 children prop을 설정하지 않아도 사용 가능합니다.
이 특수한 children prop의 값은 항상 사용자 지정 컴포넌트의 시작 태그와 종료 태그 사이에 있는 모든 콘텐츠가 됩니다.
아래의 코드에서는 <IdCard> </IdCard> 안에 있는 모든 내용이 해당됩니다.
import ItemDate from "./ItemDate";
import IdCard from './IdCard';
import "./Item.css";
function Item(props) {
return (
<IdCard className="item">
<ItemDate date= {props.date}/>
<div className="item-description">
<h2>{props.title}</h2>
<div className="item-price">${props.amount}</div>
</div>
</IdCard>
);
}
export default Item;
import './IdCard.css';
function IdCard(props){
const classes = 'idcard ' + props.className; // 사용되는 곳 마다 className이 다를 수 있기 때문에 css 적용을 위해 필요하다.
return <div className ={classes}>{props.children}</div>
}
export default IdCard;
요소들의 className도 속성으로 전달되기 때문에 props를 사용할 수 있습니다.
이렇게 컴포지션(자식 props)을 사용하면
css에 있는 중복 코드를 약간 제거하거나
모달이나 알림 같은 컴포넌트의 중복을 줄일 수 있습니다.
위 같은 경우에는 Item.css 와 IdCard.css의 중복 부분을 없애줄 수 있습니다.
'React' 카테고리의 다른 글
[React] 리액트 프로젝트 생성하기 (0) | 2023.08.02 |
---|