[React]Monster ๊ณผ์ œ

๐Ÿ™‹๐Ÿปโ€โ™€๏ธยท2022๋…„ 5์›” 20์ผ
1

wecode

๋ชฉ๋ก ๋ณด๊ธฐ
40/40

๐Ÿš€ ํ•™์Šต ๋ชฉํ‘œ

  1. useEffect()ํ›…์„ ํ†ตํ•ด data fetching ๋“ฑ ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง ์ดํ›„ ํ•„์š”ํ•œ ๋‹ค์–‘ํ•œ side effect(๋ถ€์ˆ˜ํšจ๊ณผ)๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  2. fetch() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด API ํ˜ธ์ถœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. Array.map() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด component๋ฅผ ์žฌํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  4. props ๋ฅผ ์‚ฌ์šฉํ•ด ๋‹จ๋ฐฉํ–ฅ(๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ > ์ž์‹ ์ปดํฌ๋„ŒํŠธ)์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  5. 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;

0๊ฐœ์˜ ๋Œ“๊ธ€