๐ ํ์ต ๋ชฉํ
useEffect()
ํ
์ ํตํด data fetching ๋ฑ ์ปดํฌ๋ํธ ๋ ๋๋ง ์ดํ ํ์ํ ๋ค์ํ side effect(๋ถ์ํจ๊ณผ)๋ฅผ ์ผ์ผํฌ ์ ์๋ค.
fetch()
ํจ์๋ฅผ ์ฌ์ฉํด API ํธ์ถ์ ํ ์ ์๋ค.
Array.map()
ํจ์๋ฅผ ํตํด component๋ฅผ ์ฌํ์ฉํ ์ ์๋ค.
props
๋ฅผ ์ฌ์ฉํด ๋จ๋ฐฉํฅ(๋ถ๋ชจ ์ปดํฌ๋ํธ > ์์ ์ปดํฌ๋ํธ)์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ์ ์๋ค.
Array.filter()
๋ฅผ ํตํ ๊ฒ์๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๋ค. (Optional!)
๐ด๋ชฌ์คํฐ ์นด๋ ๋์ด๋ ํ๋ฉด ๊ตฌํ ๋จผ์ ํด๋ณด๊ธฐ!(์์ฑํ๋ฉด)

โ๏ธMonster.js
import React, { useState, useEffect } from "react"; ========> useEffect ์ถ๊ฐ
import SearchBox from "./Components/SearchBox/SearchBox";
import CardList from "./Components/CardList/CardList";
import "./Monsters.scss";
/**********************************************************
API ์ฃผ์: https://jsonplaceholder.typicode.com/users
1. ์ ์ฃผ์๋ฅผ ํธ์ถํ์ฌ ๋ฐ์ดํฐ ๋ก๋ฉ์ ์ฒ๋ฆฌํด์ฃผ์ธ์!
- useEffect()
- fetch
- setState (monsters ์ ์ ์ฅ)
2. SearchBox ์ปดํฌ๋ํธ์ ์ ์ํ handleChange ๋ฉ์๋๋ฅผ ๋๊ฒจ์ฃผ๊ณ ,
ํธ์ถ ์ ์ธ์๋ก ๋ค์ด์ค๋ ์ด๋ฒคํธ๊ฐ์ฒด(e)๋ฅผ ํ์ฉํด userInput ์ผ๋ก setState.
3. ํํฐ๋ง ๋ก์ง ๊ตฌํ (filter ๋ฉ์๋ ํ์ฉ)
์ฌ๊ธฐ์ ๋น๊ต ๋์์ monster ๊ฐ์ฒด์ name ๊ฐ์
๋๋ค.
์๋ฌธ์๋ก ๋ฐ๊พผ monster.name ๊ฐ๊ณผ userInput๊ฐ์ ๋น๊ต.
filter ๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ ๋ณ์์ ์ ์ฅ ํ return ๋ฌธ ์์ CardList์ props๋ก ์ ๋ฌ
***********************************************************/
function Monsters() {
const [monsters, setMonsters] = useState([]); //์ด๊ธฐ๊ฐ ๋น๋ฐฐ์ด
const [userInput, setUserInput] = useState("");
// ๋ฐ์ดํฐ ๋ก๋ฉ
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users", {
method: "GET",
})
.then((res) => res.json()) //๋ฐ์ดํฐ ๋ณํ
.then((result) => setMonsters(result)); //๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ.
setMonsters ์
๋ ฅ ์ ์ console.log(result)๋ก ํ์ธ ํด๋ณด๊ธฐ=>array๊ฐ 10๊ฐ ํ์ธ ์.
}, []); //data fetch๋ฅผ ๋ ๋๋ง์ด ์ผ์ด๋ ์ดํ ๋จ ํ๋ฒ๋ง ์งํํ๊ธฐ ๋๋ฌธ์ ๋น ๋ฐฐ์ด์ ๋ด์
//console.log(monsters)๋ก ์ ์ฅ์ด ์ ๋์๋์ง ํ์ธํ๊ธฐ => ๋น ๋ฐฐ์ด๊ณผ 10๊ฐ์ ๊ฐ์ฒด ๋ด๊ธด๊ฒ ํ์ธ ์.
// SearchBox ์ props๋ก ๋๊ฒจ์ค handleChange ๋ฉ์๋ ์ ์
return (
<div className="monsters">
<h1>์ปดํฌ๋ํธ ์ฌ์ฌ์ฉ ์ฐ์ต!</h1>
{/* <SearchBox handleChange=์ ์ํ๋ฉ์๋ /> */}
<CardList monsters={monsters} /> //monsters๋ผ๋ props name์ผ๋ก {monsters} ์ํ๊ฐ์ ์ ๋ฌ.
</div>
);
}
export default Monsters;
โ๏ธCardList.js
import React from "react";
import Monsters from "../../Monsters";
// import Monsters from "../../Monsters";
import Card from "../Card/Card";
import "./CardList.scss";
/***********************************************************
Card ์ปดํฌ๋ํธ๋ฅผ import ํ ๋ค, props๋ก ๋ด๋ ค๋ฐ์ ๋ฐ์ดํฐ์
map ํจ์๋ฅผ ํธ์ถํด ๊ฐ๊ฐ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง Card ์ปดํฌ๋ํธ๋ค์ ๋ฆฌํดํด์ฃผ์ธ์!
Card ์ปดํฌ๋ํธ์์ ํ์๋ก ํ๋ ๋ฐ์ดํฐ๋ id, name, email ์
๋๋ค.
***********************************************************/
function CardList({ monsters }) { // ๊ตฌ์กฐ๋ถํดํ ๋น
//console.log(monsters)===> ์ฝ์ ์ฐ์ด๋ณด๋ฉด ๊ฐ์ฒด์์ id,name,email ์ฐํ
return (
<div className="cardList">
{monsters.map((monster) => { //mapํจ์์ key๊ฐ์ด ๋ฌด์กฐ๊ฑด ๋ค์ด๊ฐ์ผํจ!
return (
<Card
key={monster.id}
id={monster.id}
name={monster.name}
email={monster.email} // Card
/>
);
})}
</div>
);
}
export default CardList;
import React from "react";
import "./Card.scss";
/***********************************************************
Card ์ปดํฌ๋ํธ ๊ตฌ์กฐ
<img src=์ด๋ฏธ์ง์ฃผ์ alt="">
<h2>Name</h2>
<p>Email</p>
Card ์ปดํฌ๋ํธ์์ props๋ก ๋ฐ์์ผํ๋ ๋ฐ์ดํฐ๋ id, name, email ์
๋๋ค.
props์์ ํด๋นํ๋ ํค๊ฐ๋ค์ ์ถ์ถํ์ฌ ์์ ๊ฐ์ ๊ตฌ์กฐ๋ก ๋ง๋ค์ด์ฃผ์ธ์!
์ด๋ฏธ์ง์ฃผ์: `https://robohash.org/${์ซ์}?set=set2&size=180x180`
์นด๋๋ง๋ค ๋ค๋ฅธ ์ด๋ฏธ์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด
์ ์ฃผ์์ ์ซ์ ๋ถ๋ถ์ props๋ก ๋ด๋ ค๋ฐ์ id๋ก ๋์ฒดํ์
์ผ ํฉ๋๋ค.
Name ๊ณผ Email ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
***********************************************************/
function Card({ id, name, email }) { //๊ตฌ์กฐ๋ถํดํ ๋น
// return๋ฌธ ์์ ์ฝ๋ ์น๊ธฐ์ ์ console.log(props) ์ฐ์ด์ ํ์ธํด๋ณด๊ธฐ!!
return (
<div className="cardContainer">
<img
src={`https://robohash.org/${id}?set=set2&size=180x180`} //๊ฐ๊ฐ์ id props๋ฅผ ์ ๋ฌํจ
alt="monster"
/>
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}
export default Card;
๐ดfilter ์ฌ์ฉํ์ฌ ๊ฒ์ ๊ธฐ๋ฅ ๊ตฌํ
โ๏ธMonster.js
import React, { useState, useEffect } from "react";
import SearchBox from "./Components/SearchBox/SearchBox";
import CardList from "./Components/CardList/CardList";
import "./Monsters.scss";
/**********************************************************
API ์ฃผ์: https://jsonplaceholder.typicode.com/users
1. ์ ์ฃผ์๋ฅผ ํธ์ถํ์ฌ ๋ฐ์ดํฐ ๋ก๋ฉ์ ์ฒ๋ฆฌํด์ฃผ์ธ์!
- useEffect()
- fetch
- setState (monsters ์ ์ ์ฅ)
2. SearchBox ์ปดํฌ๋ํธ์ ์ ์ํ handleChange ๋ฉ์๋๋ฅผ ๋๊ฒจ์ฃผ๊ณ ,
ํธ์ถ ์ ์ธ์๋ก ๋ค์ด์ค๋ ์ด๋ฒคํธ๊ฐ์ฒด(e)๋ฅผ ํ์ฉํด userInput ์ผ๋ก setState.
3. ํํฐ๋ง ๋ก์ง ๊ตฌํ (filter ๋ฉ์๋ ํ์ฉ)
์ฌ๊ธฐ์ ๋น๊ต ๋์์ monster ๊ฐ์ฒด์ name ๊ฐ์
๋๋ค.
์๋ฌธ์๋ก ๋ฐ๊พผ monster.name ๊ฐ๊ณผ userInput๊ฐ์ ๋น๊ต.
filter ๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ ๋ณ์์ ์ ์ฅ ํ return ๋ฌธ ์์ CardList์ props๋ก ์ ๋ฌ
***********************************************************/
function Monsters() {
const [monsters, setMonsters] = useState([]); //์ด๊ธฐ๊ฐ ๋น๋ฐฐ์ด
const [userInput, setUserInput] = useState("");
// ๋ฐ์ดํฐ ๋ก๋ฉ
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users", {
method: "GET",
})
.then((res) => res.json()) //๋ฐ์ดํฐ ๋ณํ
.then((result) => setMonsters(result)); //๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ
}, []);
โจ // SearchBox ์ props๋ก ๋๊ฒจ์ค handleChange ๋ฉ์๋ ์ ์
const handleChange = (e) => {
setUserInput(e.target.value);
};
//console.log(userInput);===> ์ฝ์ ํ์ธ ์. (state์ ์
๋ ฅ๊ฐ์ด ์ ์ฐํ๋ค.)
//filter ๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ ๋ณ์์ ์ ์ฅ ํ return ๋ฌธ ์์ CardList์ props๋ก ์ ๋ฌ
return (
<div className="monsters">
<h1>์ปดํฌ๋ํธ ์ฌ์ฌ์ฉ ์ฐ์ต!</h1>
<SearchBox handleChange={handleChange} />
<CardList monsters={monsters} />
</div>
);
}
function Monsters() {
const [monsters, setMonsters] = useState([]); //์ด๊ธฐ๊ฐ ๋น๋ฐฐ์ด
const [userInput, setUserInput] = useState("");
// ๋ฐ์ดํฐ ๋ก๋ฉ
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users", {
method: "GET",
})
.then((res) => res.json()) //๋ฐ์ดํฐ ๋ณํ
.then((result) => setMonsters(result)); //๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ
}, []);
// SearchBox ์ props๋ก ๋๊ฒจ์ค handleChange ๋ฉ์๋ ์ ์
const updateUserInput = (e) => {
setUserInput(e.target.value);
};
//filter ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฌธ์๋ก ์
๋ ฅ์์๋ ํด๋น ๋ชฌ์คํฐ ๋ฐํํด์ฃผ๋ ํจ์
const sorterMonsters = monsters.filter((monster) => {
return monster.name.toLowerCase().includes(userInput.toLowerCase());
});
return (
<div className="monsters">
<h1>์ปดํฌ๋ํธ ์ฌ์ฌ์ฉ ์ฐ์ต!</h1>
<SearchBox handleChange={updateUserInput} /> // ํด๋น๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ณ์๋ฅผ ์ ๋ฌ. SearchBox์ handleChange์ ์์ฑ๋ช
์ผ๋ก updateUserInput๋ฅผ ์ ๋ฌ.
<CardList monsters={sorterMonsters} /> // ํด๋น๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ณ์๋ฅผ ์ ๋ฌ.
CardList์ monsters์ ์์ฑ๋ช
์ผ๋ก sorterMonsters์ ์ ๋ฌ
</div>
);
}
export default Monsters;