컴포넌트: 고유한 로직(logic)과 표현(presentation)을 가지는 사용자 인터페이스(User Interface)의 조각(Piece)
컴포넌트 크기: 버튼과 같이 작은 단위부터 페이지(Page)처럼 큰 단위일 수도 있음.
React 컴포넌트: 마크업을 반환하는 JS 함수
export function EmailInput() {
return (
<div>
<label htmlFor="email">이메일</label>
<input id="email" type="email" placeholder="user@company.io" />
</div>
);
}
EmailInput 컴포넌트를 선언했기 때문에 다른 컴포넌트 중첩해서 사용할 수 있다.
컴포넌트 이름은 파스칼 케이스(PascalCase)로 선언되어야 한다.
(리액트가 일반 함수와 컴포넌트를 구분하는 방법.)
반면에, HTML 요소 이름은 소문자로 시작한다.
대부분의 리액트 프로젝트는 편의 목적으로 JSX를 사용.
권장되는 리액트 개발 환경을 제공하는 도구는 모두 JSX를 지원한다.
<div>
또는 React.Fragment와 같은 래퍼를 사용해야 한다.import React from 'react';
function HomePage() {
return (
<React.Fragment>
<h1>홈 페이지</h1>
<div>홈(Home)은 서비스의 엔트리(Entry) 페이지입니다.</div>
</React.Fragment>
);
}
<>...</>
단축 표현도 제공한다.const HomePage = () => (
<>
<h1>홈 페이지</h1>
<div>홈(Home)은 서비스의 엔트리(Entry) 페이지입니다.</div>
</>
);
HTML class 속성처럼 React는 className prop을 설정해 동일한 방식으로 컴포넌트를 스타일링한다.
<div className="container"> ... </div>
스타일 코드는 별도로 CSS 파일에서 CSS 규칙을 사용해 작성한다.
.container {
box-sizing: border-box;
width: clamp(320px, 96vw, 1280px);
margin: 0 2vw;
}
@media (min-width: 60em) {
.container {
margin-left: auto;
margin-right: auto;
}
}
React는 스타일을 추가하는 방법을 별도로 권장 X.
외부 스타일 파일을 <link />
를 사용해 연결할 수도 있고, 빌드 툴 또는 프레임워크에서 사용 가능한 다양한 방법으로 스타일을 추가할 수 있다.
JSX를 사용한 마크업에 JS 값을 설정할 수 있다.
JS 데이터를 중괄호({})에 연결하면 그 결과를 화면에 표시할 수 있다.
function Avatar() {
return (
<img className="avatar" src={avatar.src} alt={avatar.alt} />
);
}
보다 복잡한 JS식 (expression()을 JSX 중괄호 안에 넣어 화면에 표시할 수 O)
const user = {
id: 'user-i9dk1c8',
nickname: 'yamoo9',
image: {
url: 'https://bit.ly/41fY0ae',
size: 32
},
};
export default function Profile() {
return (
<figure className="profile">
<img
alt=""
src={user.image.url}
style={{
width: user.image.size,
height: user.image.size,
}}
/>
<figcaption>{user.nickname}</figcaption>
</figure>
);
}
위 예시 코드에서
style={{}}
구문은 특별한 별도의 구문이 아니라, JS 객체({})를 JSX 중괄호 안에 넣은 것.
CSS 스타일과 같이 key, value 쌍으로 구성된 경우 반드시 객체를 값을 설정해야 정상적으로 React가 화면에 스타일링 한다.
리액트는 조건 처리를 위한 특별한 문법을 제공하지 X.
대신 JS 조건 구문을 그대로 사용.
예를 들어 조건에 따라 JSX를 포함하는 if문을 아래와 같이 작성할 수 있다.
function Dashboard() {
if (!isAuthenticated) {
return <SignInForm />
}
return (
<div className="dashboard">
{/* ... */}
</div>
);
}
if문 대신, JSX 구문 안에서 3항 연산자 식을 사용해 조건 처리 구문을 간결하게 구성할 수 있다.
function Dashboard() {
return isAuthenticated && (
<div className="dashboard">
{/* ... */}
</div>
);
}
JSX 구문 안의 속성 또한 동일한 방법으로 조건 처리가 가능.
if... else 구문을 사용해 시작할 수 있다.
JS 반복 (Loop) 구문(for 또는 Array's map 메서드 등)으로 컴포넌트를 리스트 렌더링 할 수 있다.
예를 들어 아래와 같은 products 배열을 순환해 컴포넌트 리스트 렌더링을 해보자.
const products = [
{ id: 'zd8d2jfijd', title: '카모 다운 베스트', price: 32000 },
{ id: 'op2x8idkwm', title: '플로럴 티셔츠', price: 24000 },
];
컴포넌트 내부에서 Array 객체의 map 메서드를 사용해 products 배열을 순환해 <li>
요소를 반복 구성한다.
function ProductList() {
return (
<ul>
{products.map(product => (
<li key={product.id} className="product">
<h3 className="product__title">{product.title}</h3>
<span className="product__price">{product.price}</span>
</li>
)}
</ul>
);
}
키: 데이터베이스 ID와 같은 고유한 데이터
위 예시에서 key 속성은 리스트의 각 아이템을 식별하는 고유값을 설정.
컴포넌트 내부에서 이벤트 핸들러(함수)를 선언해 이벤트를 감지해 처리.
function AppButton() {
const handleClick = () => console.log('버튼 클릭 함 🔅');
return (
<button type="button" onClick={handleClick}>클릭</button>
);
}
onClick={handleClick}
구문 안 함수 이름 끝에 괄호 ()가 없다는 점에 주목하자.
이벤트 핸들러(함수)를 호출하는 것 X, 전달만.
리액트는 사용자가 버튼을 클릭할 때 이벤트 핸들러를 호출한다.
떄때로 컴포넌트가 일부 정보를 "기억"하고 표시하길 원함.
예를 들어 버튼을 클릭한 횟수를 기억해 화면에 표시하고 싶을 수 있음.
-> 일부 정보를 기억하려면 컴포넌트에 상태(state)를 추가해야 함.
리액트는 함수 컴포넌트에서 사용할 수 있는 useState 훅을 제공한다.
컴포넌트에 상태를 설정하기 위해 상태 관리를 위한 훅을 먼저 불러와야 함.
import { useState } from 'react';
이제 useState 훅을 사용해 컴포넌트 안에서 상태 변수를 선언 및 관리 가능.
useState 훅 실행시,
배열 하나가 반환. (배열의 첫번째 항목은 현재 상태, 두 번째 항목은 상태 업데이트 함수) => ([state], [setState])
처음 화면에 표시되는 count 상태 값은 훅에 전달된 숫자 0이다.
function AppCounter() {
const [count, setCount] = useState(0);
return (
<button type="button">클릭 횟수: {count}번</button>
);
}
상태를 변경하려면 useCount 업데이트 함수에 새로운 값을 전달.
function AppCounter() {
const [count, setCount] = useState(0);
const handleCountUp = () => setCount(count + 1);
return (
<button type="button" onClick={handleCountUp}>클릭 횟수: {count}번</button>
);
}
AppCounter 컴포넌트를 구성한 후,
사용자가 화면의 카운터를 클릭하면 개별적으로 카운트 상태가 업데이트됨.
컴포넌트 자신만의 상태를 "기억"하고 개별 관리하기 때문.
function CountApp() {
return (
<>
<h2>개별적으로 업데이트 되는 카운터</h2>
<AppCounter />
<AppCounter />
</>
);
}
리액트는 함수 타입의 컴포넌트에서 사용할 수 있는 특별함 함수 "훅" 제공.
이 함수는 반드시 "use"로 시작, 이를 통해 리액트는 일반 함수와 구별한다.
내장 훅(Built-in-Hook): useState 훅은 React가 기본 제공하는 내장 훅의 대표 예시이다.
사용자가 기본 제공되는 훅 외에도 필요한 커스텀 훅을 작성할 수 있다.