보라코딩
Day 29, React 본문
오늘은 환절기... 비염 때문에 하루종일 훌쩍거렸더니 힘들다.........
리액트 공식 문서를 통해 공부했다.
생각보다 매우 잘 만들었고, 퀴즈도 있어서 흥미로웠다.
React
The library for web and native user interfaces
ko.react.dev
컴포넌트
- 컴포넌트 : 앱의 재사용 가능한 UI 요소
- React 앱에서 모든 UI는 컴포넌트
- 컴포넌트의 이름은 항상 대문자로 시작
- JSX 마크업을 반환
컴포넌트 import 와 export
App.js
import Gallery from './Gallery.js';
import { Profile } from './Gallery.js';
export default function App() {
return (
<Profile />
);
}
Gallery.js
export function Profile() {
return (
<img
src="https://i.imgur.com/QIrZWGIs.jpg"
alt="Alan L. Hart"
/>
);
}
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
JSX 규칙
- 하나의 루트 엘리먼트로 반환하기 (
- 모든 태그 닫아주기
- 캐멀케이스로 (class 대신 className 사용)
export default function TodoList() {
return (
<>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
className="photo"
/>
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
</>
);
}
JSX 안에서 자바스크립트 사용하기
- JSX에서 객체 전달하려면 이중 중괄호 사용 {{ }}
export default function Avatar() {
const avatar = 'https://i.imgur.com/7vQD0fPs.jpg';
const description = 'Gregorio Y. Zara';
return (
<img
className="avatar"
src={avatar}
alt={description}
/>
);
}
const baseUrl = 'https://i.imgur.com/';
const person = {
name: 'Gregorio Y. Zara',
imageId: '7vQD0fP',
imageSize: 's',
theme: {
backgroundColor: 'black',
color: 'pink'
}
};
export default function TodoList() {
return (
<div style={person.theme}>
<h1>{person.name}'s Todos</h1>
<img
className="avatar"
src={baseUrl + person.imageId + person.imageSize + '.jpg'}
alt={person.name}
/>
<ul>
<li>Improve the videophone</li>
<li>Prepare aeronautics lectures</li>
<li>Work on the alcohol-fuelled engine</li>
</ul>
</div>
);
}
컴포넌트에 props 전달하기
- 자식 컴포넌트에 props 전달
- 자식 컴포넌트 내부에서 props 읽기
import { getImageUrl } from './utils.js';
function Avatar({ person, size }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
export default function Profile() {
return (
<div>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
<Avatar
size={80}
person={{
name: 'Aklilu Lemma',
imageId: 'OKS67lh'
}}
/>
<Avatar
size={50}
person={{
name: 'Lin Lanying',
imageId: '1bX5QH6'
}}
/>
</div>
);
}
- spread 문법
function Profile(props) { return ( <div className="card"> <Avatar {...props} /> </div> ); }
- 컴포넌트 사용하기
import { getImageUrl } from './utils.js';
function Profile({ person, imageSize = 70 }) {
const imageSrc = getImageUrl(person)
return (
<section className="profile">
<h2>{person.name}</h2>
<img
className="avatar"
src={imageSrc}
alt={person.name}
width={imageSize}
height={imageSize}
/>
<ul>
<li>
<b>Profession:</b> {person.profession}
</li>
<li>
<b>Awards: {person.awards.length} </b>
({person.awards.join(', ')})
</li>
<li>
<b>Discovered: </b>
{person.discovery}
</li>
</ul>
</section>
)
}
export default function Gallery() {
return (
<div>
<h1>Notable Scientists</h1>
<Profile person={{
imageId: 'szV5sdG',
name: 'Maria Skłodowska-Curie',
profession: 'physicist and chemist',
discovery: 'polonium (chemical element)',
awards: [
'Nobel Prize in Physics',
'Nobel Prize in Chemistry',
'Davy Medal',
'Matteucci Medal'
],
}} />
<Profile person={{
imageId: 'YfeOqp2',
name: 'Katsuko Saruhashi',
profession: 'geochemist',
discovery: 'a method for measuring carbon dioxide in seawater',
awards: [
'Miyake Prize for geochemistry',
'Tanaka Prize'
],
}} />
</div>
);
}
- children prop에 JSX 전달하기
function Card({ children }) {
return (
<div className="card">
<div className="card-content">
{children}
</div>
</div>
);
}
export default function Profile() {
return (
<div>
<Card>
<h1>Photo</h1>
<img
className="avatar"
src="https://i.imgur.com/OKS67lhm.jpg"
alt="Aklilu Lemma"
width={100}
height={100}
/>
</Card>
<Card>
<h1>About</h1>
<p>Aklilu Lemma was a distinguished Ethiopian scientist who discovered a natural treatment to schistosomiasis.</p>
</Card>
</div>
);
}
조건부 렌더링
- 조건부로 if 문과 함께 JSX 식을 반환 가능
- 일부 JSX를 변수에 저장한 다음 중괄호를 사용하여 다른 JSX에 포함 가능
{cond ? <A /> : <B />}
: “cond이면 를 렌더링, 그렇지 않으면 를 렌더링{cond && <A />}
: “cond이면 를 렌더링, 그렇지 않으면 아무것도 렌더링하지 않음
function Item({ name, isPacked }) {
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
}
export default function PackingList() {
return (
<section>
<h1>Sally Ride's Packing List</h1>
<ul>
<Item
isPacked={true}
name="Space suit"
/>
<Item
isPacked={true}
name="Helmet with a golden leaf"
/>
<Item
isPacked={false}
name="Photo of Tam"
/>
</ul>
</section>
);
}
더 좋은 코드
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
조건부 렌더링 예시
const drinks = {
tea: {
part: 'leaf',
caffeine: '15–70 mg/cup',
age: '4,000+ years'
},
coffee: {
part: 'bean',
caffeine: '80–185 mg/cup',
age: '1,000+ years'
}
};
function Drink({ name }) {
const info = drinks[name];
return (
<section>
<h1>{name}</h1>
<dl>
<dt>Part of plant</dt>
<dd>{info.part}</dd>
<dt>Caffeine content</dt>
<dd>{info.caffeine}</dd>
<dt>Age</dt>
<dd>{info.age}</dd>
</dl>
</section>
);
}
export default function DrinkList() {
return (
<div>
<Drink name="tea" />
<Drink name="coffee" />
</div>
);
}
리스트 렌더링
- map, filter을 사용하면 특정 컴포넌트만 렌더링 가능
- map() 호출 내부의 JSX 엘리먼트에는 항상 key가 필요
import { people } from './data.js';
import { getImageUrl } from './utils.js';
export default function List() {
const chemists = people.filter(person =>
person.profession === 'chemist'
);
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
known for {person.accomplishment}
</p>
</li>
);
return <ul>{listItems}</ul>;
}
'개발자가 되었다?' 카테고리의 다른 글
Day 31, React (0) | 2023.09.27 |
---|---|
Day 30, React (0) | 2023.09.26 |
Day 28, Node.js + React (0) | 2023.09.22 |
Day 27, Typescript (0) | 2023.09.22 |
Day 26, Node.js (0) | 2023.09.20 |