[React] ๐Ÿ›‹๏ธAJAX ์‚ฌ์šฉ๋ฒ•

TATAยท2023๋…„ 2์›” 2์ผ
0

React

๋ชฉ๋ก ๋ณด๊ธฐ
8/32

โ–ท ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง ์˜ˆ์ œ

๋ชฉ๋ก์˜ ํ•„ํ„ฐ๋ง์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”
์ปดํฌ๋„ŒํŠธ์˜ ๋‚ด๋ถ€๋‚˜ ์™ธ๋ถ€์—์„œ ํ•„ํ„ฐ๋ง ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.


๐Ÿ›‹๏ธ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ํ•„ํ„ฐ๋ง

์ „์ฒด ๋ชฉ๋ก ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋ชฉ๋ก์„ ๊ฒ€์ƒ‰์–ด๋กœ filter ํ•˜๋Š” ๋ฐฉ๋ฒ•

/* storageUtil.js */
localStorage.setItem(
  "proverbs",
  JSON.stringify([
    "์ขŒ์ ˆ๊ฐ์œผ๋กœ ๋ฐฐ์›€์„ ๋Šฆ์ถ”์ง€ ๋งˆ๋ผ",
    "Stay hungry, Stay foolish",
    "Memento Mori",
    "Carpe diem",
    "๋ฐฐ์›€์—๋Š” ๋์ด ์—†๋‹ค"
  ])
);

export function getProverbs(filterBy = "") {
  const json = localStorage.getItem("proverbs");
  const proverbs = JSON.parse(json) || [];
  return proverbs.filter((prvb) =>
    prvb.toLowerCase().includes(filterBy.toLowerCase())
  );
}

------------------
/* App.js */
import { useEffect, useState } from "react";
import { getProverbs } from "./storageUtil";

export default function App() {
  const [proverbs, setProverbs] = useState([]);
  const [filter, setFilter] = useState("");

  useEffect(() => {
    console.log("์–ธ์ œ effect ํ•จ์ˆ˜๊ฐ€ ๋ถˆ๋ฆด๊นŒ?");
    const result = getProverbs();
    setProverbs(result);
  }, []);

  const handleChange = (e) => {
    setFilter(e.target.value);
  };

  return (
    <div className="App">
      ํ•„ํ„ฐ
      <input type="text" value={filter} onChange={handleChange} />
      <ul>
        {proverbs
          .filter((prvb) => {
            return prvb.toLowerCase().includes(filter.toLowerCase());
          })
          .map((prvb, i) => (
            <Proverb saying={prvb} key={i} />
          ))}
      </ul>
    </div>
  );
}

function Proverb({ saying }) {
  return <li>{saying}</li>;
}

๐Ÿ›‹๏ธ ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ ํ•„ํ„ฐ๋ง

/* storageUtil.js */
localStorage.setItem(
  "proverbs",
  JSON.stringify([
    "์ขŒ์ ˆ๊ฐ์œผ๋กœ ๋ฐฐ์›€์„ ๋Šฆ์ถ”์ง€ ๋งˆ๋ผ",
    "Stay hungry, Stay foolish",
    "Memento Mori",
    "Carpe diem",
    "๋ฐฐ์›€์—๋Š” ๋์ด ์—†๋‹ค"
  ])
);

export function getProverbs(filterBy = "") {
  const json = localStorage.getItem("proverbs");
  const proverbs = JSON.parse(json) || [];
  return proverbs.filter((prvb) =>
    prvb.toLowerCase().includes(filterBy.toLowerCase())
  );
}

------------------
/* App.js */
import { useEffect, useState } from "react";
import { getProverbs } from "./storageUtil";

export default function App() {
  const [proverbs, setProverbs] = useState([]);
  const [filter, setFilter] = useState("");
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("์–ธ์ œ effect ํ•จ์ˆ˜๊ฐ€ ๋ถˆ๋ฆด๊นŒ?");
    const result = getProverbs(filter);
    setProverbs(result);
  }, [filter]);

  const handleChange = (e) => {
    setFilter(e.target.value);
  };

  const handleCounterClick = () => {
    setCount(count + 1);
  };

  return (
    <div className="App">
      ํ•„ํ„ฐ
      <input type="text" value={filter} onChange={handleChange} />
      <ul>
        {proverbs.map((prvb, i) => (
          <Proverb saying={prvb} key={i} />
        ))}
      </ul>
      <button onClick={handleCounterClick}>์นด์šดํ„ฐ ๊ฐ’: {count}</button>
    </div>
  );
}

function Proverb({ saying }) {
  return <li>{saying}</li>;
}

๐Ÿ”ฅ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ vs ์™ธ๋ถ€

์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌ
HTTP ์š”์ฒญ์˜ ๋นˆ๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.
But, ๋ธŒ๋ผ์šฐ์ €(ํด๋ผ์ด์–ธํŠธ)์˜ ๋ฉ”๋ชจ๋ฆฌ์ƒ์—
๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๊ฒŒ ๋˜๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ์˜ ๋ถ€๋‹ด์ด ๋Š˜์–ด๋‚œ๋‹ค.

์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ ์ฒ˜๋ฆฌ
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„ํ„ฐ๋ง ๊ตฌํ˜„์„ ์ƒ๊ฐํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
But, ๋นˆ๋ฒˆํ•œ HTTP ์š”์ฒญ์ด ์ผ์–ด๋‚˜๊ฒŒ ๋˜๋ฉฐ,
์„œ๋ฒ„๊ฐ€ ํ•„ํ„ฐ๋ง์„ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ์„œ๋ฒ„๊ฐ€ ๋ถ€๋‹ด์„ ๊ฐ€์ ธ๊ฐ„๋‹ค.


โ–ท AJAX

๐Ÿ›‹๏ธ AJAX๋ž€?

Asynchronous Javascript And XML

AJAX๋ž€ ์ „์ฒด ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜์ง€ ์•Š๊ณ ๋„ ํŽ˜์ด์ง€์˜ ์ผ๋ถ€๋งŒ์„ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋ฉฐ,
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ†ตํ•ด์„œ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.(๋น„๋™๊ธฐ ํ†ต์‹ )


๐Ÿ›‹๏ธ AJAX ์š”์ฒญ ๋ณด๋‚ด๊ธฐ

// ๋ช…์–ธ์„ ์ œ๊ณตํ•˜๋Š” API์˜ ์—”๋“œํฌ์ธํŠธ๊ฐ€ http://์„œ๋ฒ„์ฃผ์†Œ/proverbs ๋ผ๊ณ  ๊ฐ€์ •.
useEffect(() => {
  fetch(`http://์„œ๋ฒ„์ฃผ์†Œ/proverbs?q=${filter}`)
    .then((response) => response.json())
    .then((json) => {
      setProverbs(json);
    });
}, [filter]);
// filter๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.

๐Ÿ›‹๏ธ ๋กœ๋”ฉ ํ™”๋ฉด ๊ตฌํ˜„ํ•˜๊ธฐ

์™ธ๋ถ€ API ์ ‘์†์ด ๋Š๋ฆด ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ,
๋กœ๋”ฉ ํ™”๋ฉด(loading indicator)์„ ๊ตฌํ˜„.

1๏ธโƒฃ ์ƒํƒœ ๊ฐ’ ๋งŒ๋“ค๊ธฐ

const [isLoading, setIsLoading] = useState(false);

2๏ธโƒฃ ์‚ผํ•ญ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ

// ์ƒ๋žต, LoadingIndicator ์ปดํฌ๋„ŒํŠธ๋Š” ๋ณ„๋„๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.
// true๋ผ๋ฉด ๋กœ๋”ฉ ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๊ณ , false๋ผ๋ฉด ๋กœ๋”ฉ ์™„๋ฃŒํ™”๋ฉด์„ ๋ณด์—ฌ์ค€๋‹ค.
return {isLoading ? <LoadingIndicator /> : <div>๋กœ๋”ฉ ์™„๋ฃŒ ํ™”๋ฉด</div>}

3๏ธโƒฃ fetch ์š”์ฒญ ์ „ํ›„๋กœ setIsLoading์„ ์„ค์ •

useEffect(() => {
  setIsLoading(true); // ๋กœ๋”ฉ ํ™”๋ฉด์„ ๋ณด์—ฌ์ค€๋‹ค.
  fetch(`http://์„œ๋ฒ„์ฃผ์†Œ/proverbs?q=${filter}`)
    .then((response) => response.json())
    .then((json) => {
      setProverbs(json);
      setIsLoading(false); // ๋กœ๋”ฉ ์™„๋ฃŒ ํ™”๋ฉด์„ ๋ณด์—ฌ์ค€๋‹ค.
    });
}, [filter]);
// filter๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.

๐Ÿ‘‰ Side Effect, Effect Hook ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

profile
๐Ÿพ

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