공부 자료 : https://react.dev/learn
React는 사용자 인터페이스(UI)를 렌더링하기 위한 JavaScript 라이브러리
- 배울 내용 : React 컴포넌트 생성, 사용자 정의, 조건부 표시
- UI → 버튼, 텍스트, 이미지와 같은 작은 단위로 구성
- React를 사용하면 재사용 가능, 중첩 가능한 컴포넌트로 결합 가능
기존에는 웹 페이지를 만들 때 콘텐츠를 마크업하고 JS를 사용해 상호 작용을 추가했음. React를 사용하면 같은 기술을 사용하면서도 상호작용을 우선시 함.
- React component는 마크업으로 뿌릴 수 있는 JavaScript 함수
**Step 1: Export the component**
export default
- 표준 JS 구문
**Step 2: Define the function**
function 함수명() {}
**Step 3: Add markup**
function Profile() {
return (
<img
src="https://i.imgur.com/MK3eW3As.jpg"
alt="Katherine Johnson"
/>
);
}
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
하나의 파일에 여러 컴포넌트를 선언할 수 있지만, 파일이 큰 경우 탐색이 어려우므로 컴포넌트를 자제 파일로 export 해서 다른 파일에서 컴포넌트를 import 하여 사용 가능
- component를 조합해 또 다른 component 생성 가능
- 여러번 중첩하게 될 경우, 파일 분리를 통해 편의성을 높일 수 있음.
function Profile() {
return (
<img
src="https://i.imgur.com/MK3eW3As.jpg"
alt="Katherine Johnson"
/>
);
}
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
위의 코드에서 Profile
, Gallery
컴포넌트는 모두 Apps.js
root componet 파일에 존재.
src/App.js
에서 실행Make a new JS file to put the components in.
Export your function component from that file (using dafault, named export)
Import it in the file where you’ll use the component (using the corresponding technique for importing default or named exports).
App.js
import Gallery from "./component/Gallery";
export default function App() {
return (
<Gallery />
);
}
Gallery.js
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>
);
}
Gallery.js
:Profile
component which is only used within the same file and is not exported.Gallery
component as a default export.App.js
:Gallery
as a default import from Gallery.js
.App
component as a default export.named export
export function Profile() {
// ...
}
import { Profile } from './Gallery.js';
On this page you learned:
보통 웹을 만들 때 HTML⇒ 컨텐츠, CSS ⇒ 디자인, JavaScript ⇒ 로직. but interactive 해지면서 로직이 컨텐츠를 결정하는 경우가 많아져 렌더링 로직과 마크업이 같은 위치의 컴포넌트에 있게 됨.
1. Return a single root element
<>, </>
- fragment, 브라우저상 HTML 트리 구조에서 흔적을 남기지 않고 그룹화해줌JSX태그를 하나로 감싸는 이유?
⇒ JSX는 HTML처럼 보이지만 내부적으로 JS 객체로 변환되기 때문에 하나의 배열로 감싸야 함.
2. Close all the tags
<img>
⇒ <img />
3. camelCase all most of the things!
Now you know why JSX exists and how to use it in components:
JSX를 사용하면 JS 파일 내에 HTML과 유사한 마크업 언어를 작성해 rendering logic과 content를 같은 위치에 둘 수 있음. JSX에서 중괄호를 사용해 마크업 안에 JavaScript 로직을 추가하거나 동적인 property를 참고할 수 있음.
export default function Avatar() {
return (
<img
className="avatar"
src="https://i.imgur.com/7vQD0fPs.jpg"
alt="Gregorio Y. Zara"
/>
);
}
{}
: " "
대신 사용. 동적으로 지정해 JS 값 사용 가능{}
중괄호 사이에는 함수 호출을 포함한 모든 JS 표현식이 작동1. JSX 태그 안에 직접 텍스트로 사용
<h1>{name}'s To Do List</h1>
⇒ O
<{tag}>Gregorio Y. Zara's To Do List</{tag}>
⇒ X
2. =
기호 바로 뒤에 오는 속성
src={avatar}
⇒ 아바타 변수
src="{avatar}"
⇒ 문자열 “{avatar}”
{{ }}
- JSX에서 JS 객체 전달, JSX 중괄호 내부의 객체style={{ }}
export default function TodoList() {
return (
<ul style={{
backgroundColor: 'black',
color: 'pink'
}}>
<li>Improve the videophone</li>
<li>Prepare aeronautics lectures</li>
<li>Work on the alcohol-fuelled engine</li>
</ul>
);
}
const person = {
name: 'Gregorio Y. Zara',
theme: {
backgroundColor: 'black',
color: 'pink'
}
};
export default function TodoList() {
return (
<div style={person.theme}>
<h1>{person.name}'s Todos</h1>
<img
className="avatar"
src="https://i.imgur.com/7vQD0fPs.jpg"
alt="Gregorio Y. Zara"
/>
<ul>
<li>Improve the videophone</li>
<li>Prepare aeronautics lectures</li>
<li>Work on the alcohol-fuelled engine</li>
</ul>
</div>
);
Now you know almost everything about JSX:
=
in attributes.{{
and }}
is not special syntax: it’s a JavaScript object tucked inside JSX curly braces.=
바로 뒤에서 작동합니다.{{
와 }}
는 특별한 구문이 아니라 JSX 중괄호 안에 들어 있는 JavaScript 객체입니다.className
, src
, alt
, width
, height
는 <img>
태그에 전달, 그 외 어떤 컴포넌트에도 props 전달 가능Step 1: Pass props to the child component (자식 컴포넌트에 props 전달)
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
Step 2: Read props inside the child component (자식 컴포넌트 내부에서 props 읽기)
function Avatar({ person, size }) {
// person and size are available here
}
🚨 props 선언 시 ()
안에 { }
잊지 않기
= 기본값
function Avatar({ person, size = 100 }) {
// ...
}
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
<Card>
<Avatar />
</Card>
children
이라는 prop으로 받음function Avatar({ person, size })
destructuring syntax.size = 100
, which is used for missing and undefined
props<Avatar {...props} />
JSX spread syntax, but don’t overuse it!<Card><Avatar /></Card>
will appear as Card
component’s children
prop.
if문
,&&
,? :
와 같은 JavaScript 구문을 사용해 조건부로 JSX를 렌더링할 수 있음.
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
null
사용return null;
? :
) - 삼항연산자if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
con ? A : B
⇒ condition 이 true이면 A 렌더링, false이면 B 렌더링&&
)return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);
if
statement.{cond ? <A /> : <B />}
means “if cond
, render <A />
, otherwise <B />
”.{cond && <A />}
means “if cond
, render <A />
, otherwise nothing”.if
.JavaScript의
filter()
,map()
을 사용해 데이터 배열을 필터링하고 component의 배열로 변환할 수 있음. 각 배열 항목마다key
를 지정해 목록이 변경되더라도 목록에서 각 항목의 위치 추적 가능
Move the data into an array
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist'
];
Map the data into a new array of JSX nodes
const listItems = people.map(person => <li>{person}</li>);
Return new array from the component
return <ul>{listItems}</ul>;
Create a new array of some conditions, by calling filter()
on the array filtering by conditions.
const chemists = people.filter(person =>
person.profession === 'chemist'
);
map over new array
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 the mapped array from the component
return <ul>{listItems}</ul>;
👉 화살표 함수(`⇒`)는 바로 뒤에 표현식을 암시적으로 Reurn하므로 `return` 문이 필요하지 않음.
하지만 중괄호(`{}`)가 오는 경우는 `return` 문 필요.
key
key를 얻는 방법
crypto.randomUUID()
, uuid
패키지 사용key 규칙
map()
.filter()
.key
on each component in a collection so React can keep track of each of them even if their position or data changes.[순수성을 어기는 예시]
let guest = 0;
function Cup() {
// Bad: changing a preexisting variable!
// 나쁨: 기존 변수를 변경합니다!
guest = guest + 1;
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
);
}
[수정]
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup guest={1} />
<Cup guest={2} />
<Cup guest={3} />
</>
);
}
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaGathering() {
let cups = [];
for (let i = 1; i <= 12; i++) {
cups.push(<Cup key={i} guest={i} />);
}
return cups;
}
event handler
useEffect
사용useEffect
.React와 많은 UI 라이브러리는 UI를 트리로 모델링
- Tree ⇒ relationship model ex)브라우저는 HTML(DOM), CSS(CSSOM) 모델링을 위해 트리 구조 사용
import * as React from 'react';
import inspirations from './inspirations';
import FancyText from './FancyText';
import Color from './Color';
export default function InspirationGenerator({children}) {
const [index, setIndex] = React.useState(0);
const inspiration = inspirations[index];
const next = () => setIndex((index + 1) % inspirations.length);
return (
<>
<p>Your inspirational {inspiration.type} is:</p>
{inspiration.type === 'quote'
? <FancyText text={inspiration.value} />
: <Color value={inspiration.value} />}
<button onClick={next}>Inspire me again</button>
{children}
</>
);
}
import