https://www.amazon.com/Best-Sellers-Books/zgbs/books
아마존 판매 사이트의 책 리스트에 관한 클론코딩을 만든다.
import React, { Fragment } from 'react';
import ReactDOM from 'react-dom/client';
const BookList = () => {
return (
<section>
<Book/>
</section>
)
}
const Book = () => {
return <article>
<Image/>
<Title/>
<Author/>
</article>
}
const Image = () => <h2>이미지 위치</h2>
const Title = () => <h2>제목</h2>
const Author = () => {
return <h4>저자</h4>
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<BookList/>)
const BookList = () => {
return (
<section>
<Book/>
<Book/>
<Book/>
<Book/>
<Book/>
</section>
)
}
컴포넌트를 생성하고 재사용하게 된다면 불필요한 코드를 줄일 수 있다.
const Image = () => (
<img src="https://images-na.ssl-images-amazon.com/images/I/61sp+sMfrXL._AC_UL600_SR600,400_.jpg"/>)
const Title = () => <h2>The Democrat Party Hates America</h2>
const Author = () => {
return <h4>Mark R. Levin</h4>
}
데이터 값이 제대로 보여주는걸 확인 할 수 있다.
index.css
* {
margin : 0;
padding : 0;
box-sizing: border-box;
}
body{
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background :#f1f5f8;
color : #222;
}
index.js
import './index.css'
* {
margin : 0;
padding : 0;
box-sizing: border-box;
}
body{
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background :#f1f5f8;
color : #222;
}
.booklist {
width: 90vw;
max-width: 1170px;
margin: 5rem auto;
display: grid;
gap: 2rem;
}
@media screen and (min-width: 768px) {
.booklist{
grid-template-columns: repeat(3,1fr);
}
}
.book {
background: #fff;
border-radius: 1rem;
padding: 2rem;
text-align: center;
}
.book img {
width: 100%;
object-fit: cover;
}
.book h2 {
margin-top: 1rem;
font-size: 1rem;
}
index.css
* {
margin : 0;
padding : 0;
box-sizing: border-box;
}
body{
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background :#f1f5f8;
color : #222;
}
index.js
import './index.css'
* {
margin : 0;
padding : 0;
box-sizing: border-box;
}
body{
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background :#f1f5f8;
color : #222;
}
.booklist {
width: 90vw;
max-width: 1170px;
margin: 5rem auto;
display: grid;
gap: 2rem;
}
@media screen and (min-width: 768px) {
.booklist{
grid-template-columns: repeat(3,1fr);
}
}
.book {
background: #fff;
border-radius: 1rem;
padding: 2rem;
text-align: center;
}
.book img {
width: 100%;
object-fit: cover;
}
.book h2 {
margin-top: 1rem;
font-size: 1rem;
}
이미지 경로
- 외부 이미지(다른 서버에 이미지를 호스팅) url 필요
- 로컬 이미지(public 폴더) - 낮은 성능
- 로컬 이미지(src 폴더) - 더 나은
<img src="./images/book-1.jpg"/>
style 속성을 사용한다.
JSX에서 {}를 사용한다는 것은 Javascript로 돌아간다는 의미
key는 그냥 value는 ''로 넣는다.
const Author = () => {
return (
<h4 style={{color: '#617d98', fontSize: '0.75', marginTop: '0.5rem'}}>
Mark R. Levin
</h4>
)
}
const Author = () => {
const inlineHeadingStyles = {
color: '#617d98',
fontSize: '0.75',
marginTop: '0.5rem'
}
return (
<h4 style={inlineHeadingStyles}>
Mark R. Levin
</h4>
)
}
css를 리팩토링하여 사용할 수 있다.
선언된 변수를 사용하기 위해서는 {}안에 넣어야한다.
{}안에 표현식은 사용할 수 없다.
const Book = () => {
const title = 'The Democrat Party Hates America'
return <article className='book'>
<img src="./images/book-1.jpg"/>
<h2>{title}</h2>
<h4>
Mark R. Levin
</h4>
</article>
}
상위 컴포넌트에 선언된 변수를 하위 컴포넌트에 넘겨 사용가능하도록 값을 넘겨받는다.
const BookList = () => {
return (
<section className="booklist">
<Book job="developer"/>
<Book title="random title" number={22}/>
</section>
)
}
const Book = (props) => {
console.log(props);
return <article className='book'>
<img src={img}/>
<h2>{title}</h2>
<h4>{author}</h4>
</article>
}
컴포넌트 속성으로 값을 넘기고 props로 받아서 사용이 가능하다.
서로 다른 종류의 값을 객체로 설정하여 다른 값을 props로 넘겨줌
const firstBook = {
author : "Mark R. Levin",
title : "The Democrat Party Hates America",
img : "./images/book-1.jpg"
}
const secondBook = {
author : "Walter Isaacson",
title : "Elon Musk",
img : "./images/book-2.jpg"
}
const BookList = () => {
return (
<section className="booklist">
<Book
author={firstBook.author}
title={firstBook.title}
img={firstBook.img}
/>
<Book
author={secondBook.author}
title={secondBook.title}
img={secondBook.img}
/>
</section>
)
}
props를 효율적으로 접근하기 위해서는 구조분해 할당을 사용하면 좋다.
여러 프로퍼티를 사용하기 위해서 변수에 할당할때 사용함.
일반적인 객체에 할당된 값에 접근
const someObject = { name : 'jaeseok', job : 'developer', location : 'seoul' } console.log(someObject.name);
구조분해 할당 객체 값 접근
const someObject = { name : 'jaeseok', job : 'developer', location : 'seoul' } const { name, job } = someObject; console.log(name)
const Book = (props) => {
return <article className='book'>
<img src={props.img} alt={props.title}/>
<h2>{props.title}</h2>
<h4>{props.author}</h4>
</article>
}
const Book = (props) => {
const {img, title, author} = props;
return <article className='book'>
<img src={img} alt={title}/>
<h2>{title}</h2>
<h4>{author}</h4>
</article>
}
props 라는 객체명을 한번만 참조하여 사용하므로 코드중복성을 제거하고 간결해진다.
const Book = ({img, title, author}) => {
return <article className='book'>
<img src={img} alt={title}/>
<h2>{title}</h2>
<h4>{author}</h4>
</article>
}
함수 파라미터 내부에서 구조 분해 할당을 해주는 방법도 가능하다.
하위 컴포넌트로 선택적인 태그를 넘겨주는건 내부에 넣어서 하면 되지않은다
<Book
author={firstBook.author}
title={firstBook.title}
img={firstBook.img}
>
<p>텍스트</p>
<button>버튼</button>
</Book>
p태그는 렌더링 되지않음
내부로 넘긴 태그는는 props객체의 children으로 넘겨준다.
const Book = ({img, title, author, children}) => {
return <article className='book'>
{children}
<img src={img} alt={title}/>
<h2>{title}</h2>
<h4>{author}</h4>
</article>
}
or
const Book = (props) => {
const {img, title, author} = props;
return <article className='book'>
{children}
<img src={img} alt={title}/>
<h2>{title}</h2>
<h4>{author}</h4>
</article>
}
순차적인 배열을 처리하기 위한 간단한 방법
배열을 순회하여 콜백함수를 실행시킴
const books = [
{
author : "Mark R. Levin",
title : "The Democrat Party Hates America",
img : "./images/book-1.jpg"
},
{
author : "Walter Isaacson",
title : "Elon Musk",
img : "./images/book-2.jpg"
}
]
const newNames = names.map((name) => {
console.log(name)
})
💡 map의 콜백함수 파라미터(name)는 임의로 설정하는 변수
순차적으로 콜백함수가 실행되는 것을 알 수 있다.
const names = ['john' , 'peter', 'susan'];
const BookList = () => {
return (
<section className="booklist">
{names.map((name) => {
return <h1>{name}</h1>
})}
</section>
)
}
배열의 내용을 잘 순회하여 렌더링이 되는 것을 알 수 있다.
books 리스트 내용 레더링
const books = [
{
author : "Mark R. Levin",
title : "The Democrat Party Hates America",
img : "./images/book-1.jpg"
},
{
author : "Walter Isaacson",
title : "Elon Musk",
img : "./images/book-2.jpg"
}
]
const BookList = () => {
return (
<section className="booklist">
{books.map((book) => {
console.log(book)
return (
<div>
<h2>{book.author}</h2>
</div>
)
})}
</section>
)
}
const BookList = () => {
return (
<section className="booklist">
{books.map((book) => {
const {img, title, author} = book;
return (
<Book img={img} title={title} author={author}></Book>
)
})}
</section>
)
}
const Book = (props) => {
const {img, title, author} = props;
return <article className='book'>
<img src={img} alt={title}/>
<h2>{title}</h2>
<h4>{author}</h4>
</article>
}
BookList 에서 books의 내용을 구조 분해 할당하여 Book 컴포넌트에서 활용
💡map을 사용할 대는 key값을 넣어주어야 한다.
(보통은 id(인덱스)값을 넣어준다.)
Spread Operation
const BookList = () => {
return (
<section className="booklist">
{books.map((book) => {
return (
<Book {...book} key={book.id}></Book>
)
})}
</section>
)
}
const Book = (props) => {
const {img, title, author} = props;
return <article className='book'>
<img src={img} alt={title}/>
<h2>{title}</h2>
<h4>{author}</h4>
</article>
}