์๋์ ๊ธ์ ์ธํ๋ฐ "์ค๋ฌด์ค์ฌ! FE ์ ๋ฌธ์๋ฅผ ์ํ React" ๊ฐ์๋ฅผ ๋ฃ๊ณ ๋ ํ์ ์ ๋ฆฌํ๊ณ ๊ธฐ๋กํ ๊ธ์ ๋๋ค.
์ปดํฌ๋ํธ๋?
- React๋ ์ปดํฌ๋ํธ๋ผ๋ ๋จ์๋ก ํ๋ฉด์ด ๊ตฌ์ฑ
- ์ค์ค๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ์บก์ํ๋ ์ฝ๋ ์กฐ๊ฐ
- ํ๋์ JSX๋ฅผ ๋ฐํํ๋ ํจ์
์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ
์๋์ App ์ปดํฌ๋ํธ๋ฅผ Hello ์ปดํฌ๋ํธ์ World ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ๊ธฐ
export default function App() {
return (
<div>
<h1>Hello,</h1>
<h2>World</h2>
</div>
);
}
[ App.js ]
import Hello from "./Hello.js";
import World from "./World.js";
export default function App() {
return (
<div>
<Hello></Hello>
<World />
</div>
);
}
[ Hello.js ]
export default function Hello() {
return <h1>Hello</h1>;
}
[ World.js ]
export default function World() {
return <h2>World</h2>;
}
** export default๋ ํ๋์ ๋ชจ๋์ ๊ฐ๋ณ์ ์ผ๋ก ๋ด๋ณด๋ด๊ธฐ ์ํด ์ฌ์ฉ
** import ๋ ๋ชจ๋์ ๋ณด๋ฌ์ค๊ธฐ ์ํด ์ฌ์ฉ
JSX์์ ์ฐจ์ด
- ์ปดํฌ๋ํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํจ์์ด๊ธฐ ๋๋ฌธ์ ์์ ๋ง์ ๊ณ ์ ํ ๋ก์ง์ด ๋ค์ด๊ฐ ์ ์๋ค.
- ์ค์ค๋ก ์ํ๋ฅผ ๊ฐ์ง ์ ์๋ค. ( ์ํ๊ฐ ๋ณํ๋ฉด ์์์ ๋ฐ์ )
์ปดํฌ๋ํธ ์์ฑ ์ ์ฃผ์์ฌํญ
- ์ปดํฌ๋ํธ ์ด๋ฆ์ PascalCase๋ก ์์ฑํด์ผํ๋ค.
- ์ปดํฌ๋ํธ๋ ์๋ฏธ ๋จ์๋ก ์ชผ๊ฐ์ ํ์ผ์ ๋ถ๋ฆฌํ๋ค.
- ์ต์์ ์ปดํฌ๋ํธ ์ด๋ฆ์ ์ผ๋ฐ์ ์ผ๋ก App์ด๋ค.
Props
- properties์ ์ค์๋ง
- ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์์ ์ปดํฌ๋ํธ๋ก ๋ด๋ ค์ฃผ๋ ๋ฐ์ดํฐ
fuction App() {
return (
<div>
<MyComponent value={'test'}/>
</div>
);
}
function MyComponent(props) {
return <div>{props.value}</div>;
}
App ์ปดํฌ๋ํธ์์ MyComponent์๊ฒ 'test'๋ผ๋ ๊ฐ์ ์ ๋ฌํ๊ณ , ์ ๋ฌ๋ฐ์ ์ปดํฌ๋ํธ๋ App์์ ํ ๋นํ value๋ผ๋ ๋ณ์๋ก ์ ๊ทผํ ์ ์๋ค.
fuction App() {
return (
<div>
<MyComponent>
<h1>value</h1>
</MyComponent>
</div>
);
}
function MyComponent(props) {
return <div>{props.children}</div>;
}
ํ์ ์ปดํฌ๋ํธ ํ๊ทธ๋ก ๊ฐ์ผ ๊ฐ์ด props๋ก ์ ๋ฌ๋ ๋์๋ children์ด๋ผ๋ ๋ณ์๋ก ์ ๊ทผํ ์ ์๋ค.
Props ํ์ฉ ํ
- ๊ตฌ์กฐ๋ถํดํ ๋น ๊ตฌ๋ฌธ์ ์ ํ์ฉํด์ผ ํ๋ค.
- ํน์ Props์ ๊ธฐ๋ณธ ๊ฐ์ ์ค ์ ์๋ค. (defaultProps)
- Props๋ ์ฝ๊ธฐ ์ ์ฉ์ด๋ค.
์์ ) ํ๋์ ์ปดํฌ๋ํธ๋ก ๋ค๋ฅธ ๊ฐ ์ถ๋ ฅํด๋ณด๊ธฐ
[ components/Heading.js ]
export default function Heading(props) {
if (props.type === "h2") {
return <h2>{props.children}</h2>;
}
return <h1>{props.children}</h1>;
}
[ App.js ]
// import Hello from "./components/Hello";
// import World from "./components/World";
import Heading from "./components/Heading";
// Heading ์ด๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ Hello, World ์ปดํฌ๋ํธ๋ฅผ ํตํฉํ๊ธฐ
export default function App() {
return (
<div>
<Heading type="h1">Hello</Heading>
<Heading type="h2">World</Heading>
</div>
);
}
State
- ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ฌ์ฉ๋๋ ์ผ์ข ์ ๋ณ์
- ์ปดํฌ๋ํธ ์ค์ค๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๊ฒ ๋ง๋๋ ์กด์ฌ
fuction App() {
const [value, setValue] = useState(0);
return {
<div>{value}</div>
};
}
useState()๋ผ๋ ํจ์๋ฅผ ํธ์ถํ๋ฉด์ ๊ทธ์ ๋ํ ๋ฐํ๊ฐ์ผ๋ก ํ๋์ State์ setterํจ์๊ฐ ๋์จ๋ค.
์์ ) ๊ฐ์ด ์ฆ๊ฐํ๋ ๋ฒํผ ๋ง๋ค๊ธฐ
// - value๋ฅผ state๋ก ๋ง๋ค๊ธฐ
// - Increase ๋ฒํผ ํจ์ ๋ง๋ค๊ธฐ (+ํจ์ํ ์ธ์๋ก)
// - Reset ๋ฒํผ ํจ์ ๋ง๋ค๊ธฐ
export default function App() {
let value = 0;
return (
<div>
<h1>value: {value}</h1>
<button
onClick={() => {
value = value + 1;
}}
>
Increase value
</button>
<button>Reset value</button>
</div>
);
}
๋ฒํผ์ ๋๋ฅด๋ฉด value๊ฐ์ ์ฆ๊ฐํ์ง๋ง, ํ๋ฉด์์๋ ๊ฐ์ด ๋ ๋๋ง๋์ง๋ ์๋๋ค.
์ง๊ธ ํ๋ฉด์ ์ฒ์ ๋ ๋๋ง๋ ํ๋ฉด ์ํ๋ก ์ฌ๋ ๋๋ง ๋์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฌ๊ธฐ์ State ํจ์๋ฅผ ์ ์ฉํด๋ณด์.
// - value๋ฅผ state๋ก ๋ง๋ค๊ธฐ
// - Increase ๋ฒํผ ํจ์ ๋ง๋ค๊ธฐ (+ํจ์ํ ์ธ์๋ก)
// - Reset ๋ฒํผ ํจ์ ๋ง๋ค๊ธฐ
import { useState } from "react";
export default function App() {
const [value, setValue] = useState(0);
return (
<div>
<h1>value: {value}</h1>
<button
onClick={() => {
console.log("Increase value1", value);
setValue(value + 1);
console.log("Increase value2", value);
}}
>
Increase value
</button>
<button
onClick={() => {
setValue(0);
}}
>
Reset value
</button>
</div>
);
}
์ฌ๊ธฐ์ useState(0)๋ผ๋ ํจ์๋ ๊ธฐ๋ณธ๊ฐ์ธ 0์ด ์ ์ฅ๋ value๋ผ๋ ๋ณ์์ setValue๋ผ๋ setter ํจ์๋ฅผ ๋ฐํํ๋ค. ์ด๋, setValue ํจ์๋ value์ ๊ฐ์ ๋ณํ์ํค๊ณ , App์ด๋ผ๋ ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ด ๋ณ๊ฒฝ๋์๋ค๋ ๊ฒ์ ๊ฐ์งํ ์ ์๋๋ก ํ๋ ํจ์์ด๋ค.
์ฌ๊ธฐ์ console์ ํ์ธํ๋ฉด
setValue() ํจ์๊ฐ ์คํ๋จ๊ณผ ๋์์ value๊ฐ ๋ณํ์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด๋ Stateํจ์๋ ๋ชจ๋ ํจ์๊ฐ ์คํ์ด ๋ ํ ํ๊บผ๋ฒ์ ๋ ๋๋งํ๊ธฐ ๋๋ฌธ์ด๋ค.
ํด๋์คํ ์ปดํฌ๋ํธ vs ํจ์ํ ์ปดํฌ๋ํธ
ํด๋์คํ ์ปดํฌ๋ํธ | ํจ์ํ ์ปดํฌ๋ํธ |
ํด๋์ ๋ฌธ๋ฒ์ผ๋ก ์์ง๋ ์ฌ์ฉ๋๊ณ ๊ตฌํํ ์๋ ์ปดํฌ๋ํธ | ๊ตฌ์กฐ๊ฐ ํด๋์ค๋ณด๋ค ๋จ์ํ ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ฉฐ ๋์ธ๋ก ์ฌ์ฉ๋๋ ์ค |
์์ง๋ ์ฌ์ฉ๋๊ณ ์๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋น์ค์์ ํ์ฉ๋๊ณ ์๊ธฐ์ ํ์ต | ์ฝ๋ ์ฌํ์ฉ์ฑ์ ์ ๋ฆฌํ ์๋ก์ด ์ปดํฌ๋ํธ ์ ์ ๋ฐฉ์ |
ํด๋์คํ ์ปดํฌ๋ํธ
ํด๋์ค ๋ฌธ๋ฒ์ผ๋ก ๊ตฌํํ ์ปดํฌ๋ํธ
์์ ) ์์ ๊ตฌํํ ๊ฐ์ด ์ฆ๊ฐํ๋ ๋ฒํผ ๋ง๋ค๊ธฐ๋ฅผ ํด๋์คํ์ผ๋ก ๊ตฌํ
import React, { Component } from 'react';
export default class App extends Component {
state = {
value: 0
};
constructor(props) {
super(props);
this.state = {
value: 1
};
}
resetValue() {
this.setState({ value: 0 });
}
render() {
return (
<div>
<h1>value: {this.state.value}</h1>
<button
onClick={() => {
this.setState((state) => ({
value: state.value + 1
}));
}}
>
Increase value
</button>
<button
onClick={this.resetValue.bind(this)}
>
Reset value
</button>
</div>
);
}
}
ํด๋์ค๊ฐ ์ปดํฌ๋ํธ๊ฐ ๋๊ธฐ ์ํด์ react์ ์๋ Component๋ฅผ ์์๋ฐ์์ผ ํ๋ค.
[ ํด๋์คํ ์ปดํฌ๋ํธ ]
[ ํจ์ํ ์ปดํฌ๋ํธ ]
state ๋ณ์๋ฅผ ํ ๋นํ๋ ๋ฐ ์์ด์ ์ฐจ์ด๊ฐ ๋๋ค.
this.resetValue์์์ this๋ App ํจ์ ์ ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด ์๋ onClick์ด๋ผ๋ ์์๊ฐ ์คํ๋ button์ ๊ฐ๋ฆฌํค๊ฒ ๋๋ค. ํ์ง๋ง, button์ setState๋ฅผ ๊ฐ์ง๊ธฐ ์๊ธฐ ๋๋ฌธ์ ์ค๋ฅ๊ฐ ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํ์ฌ App์ ๊ฐ๋ฆฌํค๋ this๋ฅผ bind๋ฅผ ํด์ค์ผ๋ง ํ๋ค.
Hooks์ ๋ฑ์ฅ ์ด์
์ปดํฌ๋ํธ์ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด ๋ณต์กํ ๋ผ์ดํ ์ฌ์ดํด๋ก ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ด๋ ต๊ณ , ์ฝ๋์ ์ฌํ์ฉ์ฑ์ด ๋จ์ด์ง๋ฉด์ ์๋ก์ด ๋ฐฉ์์ ๊ณ ์ํ๊ฒ ๋์๋ค. ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ ๋์ ํ๋ฉด์ ํจ์์ state๋ฅผ ์ ์ํ๊ธฐ ์ํด hooks๋ผ๋ ๊ฐ๋ ์ด ์ฌ์ฉ๋์๋ค.
์ค์ต) ์คํฐ๋ํ์ด ๊ฐ์ ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ
[ App.js ]
import CourseCard from './components/CourseCard';
function App() {
return (
<div style={{ padding: 30 }}>
<CourseCard
img="https://dst6jalxvbuf5.cloudfront.net/media/images/Course/cover_image/210909_191531/23.png"
tags={['๋ฐํ', 'ํจํค์ง', '์ต๋ํ ์ธ']}
title="๋น์ฆ๋์ค ์ฌ์ธ์, ๋ฐฉ๊ตฌ์ ์ดํ์ฐ์ ํจํค์ง"
startPrice={349000}
types={['๋์์ ๊ฐ์']}
/>
</div>
);
}
export default App;
[ CourseCard.js ]
import "./CourseCard.css";
function CourseCard({ img, tags, title, startPrice, types }) {
return (
<div className="CourseCard">
<div className="cover">
<img src={img} alt="" />
</div>
<div>
<ul className="tags">
{tags.map((item, idx) => (
<li key={idx} className="tag">
{item}
</li>
))}
</ul>
</div>
<div className="name">{title}</div>
<div className="price">{startPrice.toLocaleString()}์๋ถํฐ</div>
<div>
<ul className="types">
{types.map((item, idx) => (
<li key={idx} className="type">
{item}
</li>
))}
</ul>
</div>
</div>
);
}
export default CourseCard;