๋ชฉ๋ก์ ํํฐ๋ง์ ๊ตฌํํ๊ธฐ ์ํด์๋
์ปดํฌ๋ํธ์ ๋ด๋ถ๋ ์ธ๋ถ์์ ํํฐ๋ง ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
์ ์ฒด ๋ชฉ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๊ณ , ๋ชฉ๋ก์ ๊ฒ์์ด๋ก 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>;
}
์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ฒ๋ฆฌ
HTTP ์์ฒญ์ ๋น๋๋ฅผ ์ค์ผ ์ ์๋ค.
But, ๋ธ๋ผ์ฐ์ (ํด๋ผ์ด์ธํธ)์ ๋ฉ๋ชจ๋ฆฌ์์
๋ง์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ฒ ๋๋ฏ๋ก, ํด๋ผ์ด์ธํธ์ ๋ถ๋ด์ด ๋์ด๋๋ค.
์ปดํฌ๋ํธ ์ธ๋ถ์์ ์ฒ๋ฆฌ
ํด๋ผ์ด์ธํธ๊ฐ ํํฐ๋ง ๊ตฌํ์ ์๊ฐํ์ง ์์๋ ๋๋ค.
But, ๋น๋ฒํ HTTP ์์ฒญ์ด ์ผ์ด๋๊ฒ ๋๋ฉฐ,
์๋ฒ๊ฐ ํํฐ๋ง์ ์ฒ๋ฆฌํ๋ฏ๋ก ์๋ฒ๊ฐ ๋ถ๋ด์ ๊ฐ์ ธ๊ฐ๋ค.
Asynchronous Javascript And XML
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๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์คํ๋๋ค.