실습 환경 설정하기
본격적인 실습에 앞서 5장에서 사용할 새 리액트 앱을 만든다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
// import reportWebVitals from './reportWebVitals'; // 앞서 삭제한 파일을 불러오는 문장, 리액트 앱의 성능 척도 측정용도로 사용
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// // 리액트 앱 내부의 잠재적인 문제를 검사하는 도구, 리액트 입문자에 혼란을 줄 수 있음
//
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: <https://bit.ly/CRA-vitals>
// reportWebVitals();
import './App.css';
function App() {
return (
<div className="App"></div>
);
}
export default App;
첫 컴포넌트 만들기
리액트 컴포넌트는 주로 자바스크립트의 클래스나 함수를 이용해 만든다. 클래스로 컴포넌트를 만드는 방식은 기본 설정 코드를 작성하는 등 함수로 만드는 컴포넌트에 비해 단점이 많아 지금은 선호하지 않는다.
따라서 함수로 컴포넌트를 만드는 방법을 알아보도록 하자.
const Header = () => {
return (
<header>
<h1>header</h1>
</header>
);
};
📌 컴포넌트 이름은 HTML 태그와 구분하기 위해 항상 대문자로 시작한다.function App() {
return (
<div className="App">
<Header />
</div>
);
}
리액트는 다른 컴포넌트를 태그로 감싸 사용한다. 이때 App처럼 다른 컴포넌트를 return문 내부에 포함하는 컴포넌트를 ‘부모 컴포넌트’라고 하며, 부모의 return문에 포함된 컴포넌트를 ‘자식 컴포넌트’라고 한다.이렇게 부모의 return문에 자식을 포함하는 행위를 “자식 컴포넌트를 배치한다”라고 표현한다.
컴포넌트의 계층 구조
리액트 컴포넌트는 부모-자식 관계라는 계층 구조를 형성하며 ‘컴포넌트 트리’라고 한다. 그리고 컴포넌트 트리에서 App은 항상 최상위에 존재하므로 ‘루트 컴포넌트’라고 한다.
컴포넌트별로 파일 분리하기
리액트에서는 가독성을 위해 보통 하나의 파일에 하나의 컴포넌트를 만든다.
이번에는 컴포넌트 파일만을 따로 모아 보관할 폴더를 만들고 컴포넌트를 여러 파일로 나누어 보도록 하자.
const Header = () => {
return (
<header>
<h1>header</h1>
</header>
);
};
export default Header; // Header 컴포넌트를 다른 파일에서 사용할 수 있도록 내보냄
const Body = () => {
return (
<div>
<h1>body</h1>
</div>
);
};
export default Body;
const Footer = () => {
return (
<div>
<h1>footer</h1>
</div>
);
};
export default Footer;
import './App.css';
import Header from "./component/Header";
import Body from "./component/Body";
import Footer from "./component/Footer";
function App() {
return (
<div className="App">
<Header />
<Body />
<Footer />
</div>
);
}
export default App;
JSX란?
리액트에서 컴포넌트는 자바스크립트 함수로 만들고 HTML 값을 반환한다. JSX는 자바스크립트와 HTML 태그를 섞어 사용하는 문법이다. 공식 자바스크립트 문법은 아니지만, 자바스크립트의 확장 문법이며 다수의 리액트 개발자가 사용한다. 또한, 리액트 공식문서와 리액트 개발팀 또한 JSX 문법 사용을 적극 권장한다.
JSX 문법을 이용하면 다음과 같이 HTML 태그에서 자바스크립트의 표현식을 직접 사용할 수 있다.
const number = 1;
return (
<div>
<h2>{number}</h2>
</div>
);
JSX와 자바스크립트 표현식
표현식은 값으로 표현되는 평가식이다. JSX는 자바스크립트 표현식을 HTML 태그와 함게 사용할 수 있어 가독성 있는 코드를 작성할 수 있다.
자주 사용하는 표현식을 살펴보도록 하자.
const numA = 1;
const numB = 2;
return (
<div>
<h2>{numA + numB}</h2>
</div>
);
const strA = "안녕";
const strB = "리액트";
return (
<div>
<h2>{strA + strB}</h2>
</div>
);
const boolA = true;
const boolB = false;
return (
<div>
<h2>{boolA || boolB}</h2>
</div>
);
JSX는 값을 반환하는 자바스크립트 표현식을 사용할 수 있지만, 모든 값을 사용할 수 있는 것은 아니다. 원시 자료형에 해당하는 숫자, 문자열, 불리언, null, undefined를 제외한 값을 사용하면 오류가 발생한다.
const objA = {
a: 1,
b: 2,
};
return (
<div>
<h2>a: {objA.a}</h2>
<h2>b: {objA.b}</h2>
</div>
);
JSX 문법에서 지켜야 할 것들
const Body = () => {
return (
<div>div 1</div>
<div>div2</div>
);
};
const Body = () => {
return (
<React.Fragment>
<div>div 1</div>
</React.Fragment>
);
};
조건부 렌더링
조건부 렌더링은 리액트 컴포넌트가 조건식의 결과에 따라 각기 다른 값을 페이지에 렌더링하는 것이다. 조건에 따라 페이지 요소의 모습이나 종류를 다르게 표시하고 싶을 때 사용한다.
import React from "react";
const Body = () => {
const num = 19;
return (
<>
<h2>
{num}은 {num % 2 === 0 ? "짝수" : "홀수"}입니다.
</h2>
</>
);
};
export default Body;
2. 조건문을 이용한 조건부 렌더링
import React from "react";
const Body = () => {
const num = 200;
if (num % 2 === 0) {
return <div>{num}은 짝수입니다. </div>
} else {
return <div>{num}은 홀수입니다. </div>
}
};
export default Body;
JSX 스타일링
스타일링이란 CSS와 같은 스타일 규칙을 이용해 요소의 크기, 색상 등을 결정하는 일이다.
JSX로 리액트 컴포넌트를 스타일링하는 방법을 알아보도록 하자.
return (
<div style={{ backgroundColor: "red", color: "blue" }}>
<h1>body</h2>
</div>
);
import "./Body.css";
const Body = () => {
return (
<div className="body">
<h1>body</h1>
</div>
);
};
export default Body;
.body{
background-color: green;
color: blue;
}
Props란?
리액트에서는 부모가 자식 컴포넌트에 단일 객체 형태로 값을 전달할 수 있는데, 이 객체를 Props라고 한다. Props는 Properties의 줄임말로 속성이라는 뜻이다.
Props로 값 전달하기
전달하는 Props는 단일 객체이므로 객체 Props에는 name 프로퍼티가 추가된다.
import Body from "./component/Body";
function App() {
const name="이정환";
return (
<div className="App">
<Body name={name} />
</div>
);
}
export default App;
import "./Body.css";
function Body(props){
console.log(props); // 값 확인을 위한 콘솔 창 출력
return <div className="body">{props.name}</div>; // 렌더링
}
export default Body;
2. Props로 여러 개의 값 전달하기
import Body from "./component/Body";
function App() {
const name="이정환";
return (
<div className="App">
<Body name={name} location={"부천시"} />
</div>
);
}
export default App;
import "./Body.css";
function Body(props){
console.log(props);
return <div className="body">{props.name}은 {props.location}에 거주합니다.</div>;
}
export default Body;
3. 구조 분해 할당으로 여러 개의 값 사용하기
자식 컴포넌트에서 Props로 전달된 값이 많을 경우, 이 값을 사용할 때마다 객체의 점 표기법을 사용해야하는 불편함 이 있기 때문에 구조 분해 할당을 통해 편하게 사용할 수 있다. → Props도 객체이기 때문!
// 매개변수 props에 있는 프로퍼티를 구조 분해 할당하여 같은 이름의 상수에 저장
function Body(props){
const {name, location} = props;
console.log(name, location);
return <div className="body">
{name}은 {location}에 거주합니다.
</div>;
}
// 매개변수에 구조 분해 할당하기 -> 더 간단한 코드 작성
function Body({name, location}) {
console.log(name, location);
return (
<div className="body">
{name}은 {location}에 거주합니다.
</div>
);
}
4. 스프레드 연산자로 여러 개의 값 쉽게 전달하기
3.과 반대로 부모 컴포넌트에서 Props로 전달할 값이 많은 경우, 값을 일일이 명시해야하므로 불편하고 가독성이 떨어진다. Props로 값을 하나의 객체로 만든 다음, 스프레드 연산자를 활용해 전달하여 간결하게 작성한다.
import Body from "./component/Body";
function App() {
const BodyProps={
name: "이정환",
location: "부천시",
};
return (
<div className="App">
<Body {...BodyProps} />
</div>
);
}
export default App;
import "./Body.css";
function Body({name, location}){
console.log(name, location);
return <div className="body">
{name}은 {location}에 거주합니다.
</div>;
}
export default Body;
5. 기본값 설정하기
기본값 설정을 통해 컴포넌트가 받을 Props의 기본값을 미리 설정해 오류를 미연에 방지하도록 한다.
import Body from "./component/Body";
function App() {
const BodyProps={
name: "이정환",
location: "부천시",
// favorList: ["파스타", "빵", "떡볶이"],
};
...
import "./Body.css";
function Body({name, location, favorList}) {
console.log(name, location, favorList);
return (
<div className="body">
{name}은 {location}에 거주합니다.
<br />
{favorList.length}개의 음식을 좋아합니다.
</div>
);
}
Body.defaultProps = {
favorList: [],
};
export default Body;
Props로 컴포넌트 전달하기
지금까지는 컴포넌트 간에 Props로 문자열이나 숫자 같은 자바스크립트 값을 전달해 보았다면, 이번엔 컴포넌트 값도 전달하는 방법을 알아보자.
import Body from "./component/Body";
function ChildComp(){ // 새로운 Component 생성
return <div>child component</div>
}
function App() {
return (
<div className="App">
<Body>
<ChildComp /> // 자식요소로 배치
</Body>
</div>
);
}
export default App;
import "./Body.css";
function Body({children}) {
console.log(children);
return (
<div className="body">
{children}
</div>
);
}
export default Body;
컴포넌트가 콘솔에서 객체 형식의 값을 출력한다.
이 객체는 리액트 컴포넌트를 표현한 것이므로 오류가 발생하지 않는다.
✔️ JSX에서는 자바스크립트 표현식이 객체를 평가할 경우 오류가 발생한다.
<프로그래밍 문제>
1. 다음 코드는 JSX 문법에서 어떤 규칙을 위반한 것인지 주석으로 쓰고 오류가 나지 않게 수정하시오. (복수 정답 인정)
const Body = () => {
return (
<div>div 1</div>
);
};
2. 다음 App.js에 새로 생성된 ChildComp 컴포넌트를 Body 컴포넌트의 자식 컴포넌트에 배치하고 Body 컴포넌트를 작성하시오.
import Body from "./component/Body";
function ChildComp(){
return <div>child component</div>
}
function App() {
return (
<div className="App">
<Body />
</div>
);
}
export default App;
1. 최상위 태그 규칙을 위반함.
const Body = () => {
return (
<React.Fragment>
<div>div 1</div>
</React.Fragment>
);
};
또는 빈태그 사용
const Body = () => {
return (
<>
<div>div 1</div>
</>
);
};
2.
- App.js
import Body from "./component/Body";
function ChildComp(){ // 새로운 Component 생성
return <div>child component</div>
}
function App() {
return (
<div className="App">
<Body>
<ChildComp /> // 자식요소로 배치
</Body>
</div>
);
}
export default App;
- Body.js
function Body({children}) {
console.log(children);
return (
<div className="body">
{children}
</div>
);
}
export default Body;
출처 : 이정환, 『한 입 크기로 잘라먹는 리액트』, 프로그래밍인사이트(2023), p184 - 220.
Corner React.js 3
Editor: so2
[리액트 스타터3] project 1 [카운터] 앱 만들기 6장. 라이프 사이클과 리액트 개발자 도구 (0) | 2023.11.17 |
---|---|
[리액트 스타터3] 5장. 리액트의 기본 기능 다루기 2 (0) | 2023.11.10 |
[React.js 3] 3장. Node.js - 4장. 리액트 시작하기 (0) | 2023.10.13 |
[React.js 3] 2장. 자바스크립트 실전 (0) | 2023.10.06 |
[React.js 3] 1장. 자바스크립트 기초 (0) | 2023.09.29 |