const name = 'Josh Perez’;
const element = <h1>Hello, {name}</h1>;
React.createElement(component, props, …children) function
반드시 부모 요소 하나가 감싸는 형태여야 한다.
< >
is a fragment (<>
...</>
syntax or <React.Fragment>...</React.Fragment>)<>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
/>
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
</>
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}
/>
);
}
export default function TodoList() {
return (
<ul style={{backgroundColor: 'black', color: 'pink'}}>
<li>Improve the videophone</li>
</ul>);
function Welcome(props) {
return <h1>Welcome Back, {props.name}</h1>;
}
React 컴포넌트는 자신의 props에 대해 순수 함수(pure function)처럼 동작해야 한다
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
<Avatar person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} size={100} />
// Avatar 컴포넌트 내부에서의 예상 코드
function Avatar({ person, size }) {
const { name, imageId } = person;
return (
<div>
<img
src={`https://example.com/images/${imageId}.jpg`}
alt={name}
style={{ width: size, height: size }}
/>
<p>{name}</p>
</div>
);
}
import React from 'react';
// Avatar 컴포넌트 정의
function Avatar({ size = 50 }) {
return (
<div>
<p>Avatar Size: {size}</p>
</div>
);
}
// 부모 컴포넌트에서 Avatar를 사용하는 예제
function ParentComponent() {
return (
<div>
{/* size 프롭을 전달하지 않을 경우, 디폴트 값인 50이 사용됨 */}
<Avatar />
{/* size 프롭을 명시적으로 전달하면 전달된 값이 사용됨 */}
<Avatar size={100} />
{/* size 프롭을 undefined로 전달하면 디폴트 값인 50이 사용됨 */}
<Avatar size={undefined} />
{/* size 프롭을 null로 전달하면 디폴트 값이 사용되지 않음 */}
<Avatar size={null} />
{/* size 프롭을 0으로 전달하면 디폴트 값이 사용되지 않음 */}
<Avatar size={0} />
</div>
);
}
export default ParentComponent;
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
Avatar 컴포넌트에 프로필 정보를 forwarding
//App.js
import Gallery from './Gallery.js';
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>
);
}
import { getImageUrl } from './utils.js';
function Avatar(prop) {
return (
<img
className="avatar"
src={getImageUrl(prop.person)}
alt={prop.person.name}
width={prop.size}
height={prop.size}
/>
);
}
export default function Profile() {
return (
<div>
<Avatar
size={50}
person={{
name: 'Lin Lanying',
imageId: '1bX5QH6'
}}
/>
</div>
);
}
export function getImageUrl(person, size = 's') {
return (
'https://i.imgur.com/' +
person.imageId +
size +
'.jpg'
);
}
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
체크된 자리에 null도 넣을수 있다~
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>
);
}
Conditional (ternary) operator (? :)
function Item({ name, isPacked }) {
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
}
체크된 자리에 null을 넣을수 있다~ if문 대신 3항 연산자도 가능하다
<ul>
<ul>
<li>Creola Katherine Johnson: mathematician</li>
<li>Mario José Molina-Pasquel Henríquez: chemist</li>
<li>Mohammad Abdus Salam: physicist</li>
<li>Percy Lavon Julian: chemist</li>
<li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>
를 아래처럼 바꿀 수 있다.
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist
];
export default function List() {
const listItems = people.map(person =>
<li>{person}</li>
);
return <ul>{listItems}</ul>;
}
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);
const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathematician',
accomplishment: 'spaceflight calculations',
imageId: 'MK3eW3A'
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chemist',
accomplishment: 'discovery of Arctic ozone hole',
imageId: 'mynHUSa'
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicist',
accomplishment: 'electromagnetism theory',
imageId: 'bE7W1ji'
}];
filter()
on the people
filtering by person.profession === 'chemist'
map()
over chemists
//App.js
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>;
}
React 컴포넌트에서 렌더링에 사용되는 입력값(Props, State, Context 등)을 직접 수정하거나 변경해서는 안 된다. 렌더링에 사용되는 입력값을 직접 변경하지 말고, 필요한 경우에는 지역적으로(mutate locally)만 변경해야 한다.
// Side Effect
let guest = 0;
function Cup() {
guest = guest + 1;
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
);
}
이 코드가 두 번 실행되는 이유는 JSX에서 컴포넌트를 렌더링할 때 React는 먼저 컴포넌트 함수를 실행하여 반환 값(렌더링 될 JSX)을 얻고, 그 다음 실제로 JSX를 렌더링합니다.
따라서, guest = guest + 1; 코드는 한 번은 컴포넌트 함수를 실행할 때, 다른 한 번은 JSX를 렌더링할 때 실행되어 총 두 번 실행됩니다. 그래서 guest의 값이 2씩 증가하는 것입니다.
// No Side Effect
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} />
</>
);
}