Jieunny์ ๋ธ๋ก๊ทธ
S2) Unit 9. [React] Effect Hook ๋ณธ๋ฌธ
๐ฃ Side Effect(๋ถ์ ํจ๊ณผ)
โ๏ธ ํจ์ ๋ด์์ ์ด๋ค ๊ตฌํ์ด ํจ์ ์ธ๋ถ์ ์ํฅ์ ๋ผ์น๋ ๊ฒฝ์ฐ ํด๋น ํจ์๋ Side Effect๊ฐ ์๋ค๊ณ ๋งํ๋ค.
โ๏ธ ๋ฆฌ์กํธ์์๋ ์ปดํฌ๋ํธ ๋ด์์ fetch๋ฅผ ์ฌ์ฉํด API ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ด๋ฒคํธ๋ฅผ ํ์ฉํด DOM์ ์ง์ ์กฐ์ํ ๋ Side Effect๊ฐ ๋ฐ์ํ๋ค๊ณ ๋งํ๋ค.
๐ฃ Pure Function(์์ ํจ์)
โ๏ธ ์ค์ง ํจ์์ ์ ๋ ฅ๋ง์ด ํจ์์ ๊ฒฐ๊ณผ์ ์ํฅ์ ์ฃผ๋ ํจ์
โ๏ธ ํจ์์ ์ ๋ ฅ์ด ์๋ ๋ค๋ฅธ ๊ฐ์ด ํจ์์ ๊ฒฐ๊ณผ์ ์ํฅ์ ๋ฏธ์น๋ ๊ฒฝ์ฐ ์์ ํจ์๋ผ๊ณ ๋ถ๋ฅผ ์ ์๋ค.
โ๏ธ ์ ๋ ฅ์ผ๋ก ์ ๋ฌ๋ ๊ฐ์ ์์ ํ์ง ์์์ผ ํ๋ค.
function upper(str) {
return str.toUpperCase(); // toUpperCase ๋ฉ์๋๋ ์๋ณธ์ ์์ ํ์ง ์์ต๋๋ค (Immutable)
}
upper('hello') // 'HELLO'
โฐ ์์ ํจ์์๋ ๋คํธ์ํฌ ์์ฒญ๊ณผ ๊ฐ์ Side Effect๊ฐ ์๋ค.
โฐ ์ด๋ค ์ ๋ฌ ์ธ์๊ฐ ์ฃผ์ด์ง ๊ฒฝ์ฐ, ํญ์ ๋๊ฐ์ ๊ฐ์ด ๋ฆฌํด๋จ์ ๋ณด์ฅํ๋ค -> ์์ธก ๊ฐ๋ฅํ ํจ์
๐ฃ React์ ํจ์ ์ปดํฌ๋ํธ
โ๏ธ AJAX ์์ฒญ(fetch API)์ด ํ์ํ๊ฑฐ๋, LocalStorage ๋๋ ํ์ด๋จธ(setTimeout)์ ๊ฐ์ React์ ์๊ด์๋ API๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ฆฌ์กํธ ์ ์ฅ์์๋ ๋ชจ๋ Side Effect ์ด๋ค.
โ๏ธ ๋ฆฌ์กํธ์์๋ Side Effect๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํ Hook์ธ Effect Hook์ ์ ๊ณตํ๋ค.
๐ฃ Effect Hook
โ๏ธ ์ปดํฌ๋ํธ๋ด์์ Side effect๋ฅผ ์คํํ ์ ์๊ฒ ํ๋ Hook
โ๏ธ useEffect(ํจ์) : ์ธ์๋ก ๋ฐ์ ํจ์ ๋ด์์ Side effect๋ฅผ ์คํํ๋ฉด ๋๋ค.
โฐ ์ปดํฌ๋ํธ ์์ฑ ํ ์ฒ์ ํ๋ฉด์ ๋ ๋๋ง
โฐ ์ปดํฌ๋ํธ์ ์๋ก์ด props๊ฐ ์ ๋ฌ๋๋ฉฐ ๋ ๋๋ง
โฐ ์ปดํฌ๋ํธ์ ์ํ(state)๊ฐ ๋ฐ๋๋ฉฐ ๋ ๋๋ง
โ๏ธ ์์ ๊ฐ์ด ๋งค๋ฒ ์๋กญ๊ฒ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ๋ Effect Hook์ด ์คํ๋๋ค.
๐จ Hook ์ฌ์ฉ ์ ์ฃผ์์ฌํญ
โฐ ์ต์์์์๋ง Hook์ ํธ์ถํ๋ค.
โฐ React ํจ์ ๋ด์์ Hook์ ํธ์ถํ๋ค.
// ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ์์ฑ๋๊ฑฐ๋, props๊ฐ ์
๋ฐ์ดํธ ๋๊ฑฐ๋, state๊ฐ ์
๋ฐ์ดํธ ๋ ๋๋ง๋ค ์คํ
useEffect(() => {
console.log(๋ช ๋ฒ ํธ์ถ๋ ๊น์?)
})
// ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ์์ฑ๋ ๋๋ง ํจ์๊ฐ ์คํ
useEffect(() => {
console.log(๋ช ๋ฒ ํธ์ถ๋ ๊น์?)
},[])
// dep์ด ์
๋ฐ์ดํธ ๋ ๋๋ง๋ค ์คํ
useEffect(() => {
console.log(๋ช ๋ฒ ํธ์ถ๋ ๊น์?)
},[dep])
๐ฃ ์กฐ๊ฑด๋ถ Effect ๋ฐ์
โ๏ธ useEffect์ ๋๋ฒ์งธ ์ธ์๋ ๋ฐฐ์ด
โฐ ๋ฐฐ์ด์ ์กฐ๊ฑด์ ๋ด๊ณ ์์ผ๋ฉฐ, ์ด๋ค ๊ฐ์ ๋ณ๊ฒฝ์ด ์ผ์ด๋ ๋๋ฅผ ์๋ฏธํ๋ค.
โฐ ํด๋น ๋ฐฐ์ด์๋ ์ด๋ค ๊ฐ์ด ๋ค์ด๊ฐ๋ค -> ์ข ์์ฑ ๋ฐฐ์ด์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
useEffect(ํจ์, [์ข
์์ฑ1, ์ข
์์ฑ2, ...])
โฐ ๋ฐฐ์ด ๋ด์ ์ข ์์ฑ1 ๋๋ ์ข ์์ฑ2์ ๊ฐ์ด ๋ณํ ๋, ์ฒซ๋ฒ์งธ ์ธ์์ธ ํจ์๊ฐ ์คํ๋๋ค.
โฐ ๋ฐฐ์ด ๋ด์ ์ด๋ค ๊ฐ์ด ๋ณํ ๋๋ง ํจ์๊ฐ ์คํ๋๋ค.
โฐ ๋น ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด ์ฒ์ ๋จ ํ๋ฒ, ์ธ๋ถ API๋ฅผ ํตํด ๋ฆฌ์์ค๋ฅผ ๋ฐ์์ค๊ณ ๋ ์ด์ API ํธ์ถ์ด ํ์ํ์ง ์์ ๋์ ์ฌ์ฉํ ์ ์๋ค.
๐ฃ ์ปดํฌ๋ํธ ๋ด์์์ Ajax ์์ฒญ
โ๏ธ Data Fetching : ํํฐ๋ง
1๏ธโฃ ์ปดํฌ๋ํธ ๋ด์์ ํํฐ๋ง : ์ ์ฒด ๋ชฉ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๊ณ , ๋ชฉ๋ก์ ๊ฒ์์ด๋ก filter ํ๋ ๋ฐฉ๋ฒ
import { useEffect, useState } from "react";
import "./styles.css";
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>;
}
โฐ ์ฒ์ ํ๋ฒ๋ง ์ธ๋ถ API์์ ๋ช ์ธ ๋ชฉ๋ก์ ๋ฐ์์ค๊ณ , filter ํจ์๋ฅผ ์ด์ฉํ๋ค.
2๏ธโฃ ์ปดํฌ๋ํธ ์ธ๋ถ์์ ํํฐ๋ง : ์ปดํฌ๋ํธ ์ธ๋ถ๋ก API ์์ฒญ์ ํ ๋, ํํฐ๋ง ํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ค๋ ๋ฐฉ๋ฒ(์๋ฒ์ ๋งค๋ฒ ๊ฒ์์ด์ ํจ๊ป ์์ฒญํ๋ ๊ฒฝ์ฐ๊ฐ ํด๋น)
import { useEffect, useState } from "react";
import "./styles.css";
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]); // 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>;
}
โฐ ๊ฒ์์ด๊ฐ ๋ฐ๋ ๋๋ง๋ค ์ธ๋ถ API๋ฅผ ํธ์ถํ๋ค.
๐ฃ ์ฅ, ๋จ์
์ฅ์ | ๋จ์ | |
์ปดํฌ๋ํธ ๋ด๋ถ | HTTP ์์ฒญ ๋น๋ ๊ฐ์ | ๋ธ๋ผ์ฐ์ (ํด๋ผ์ด์ธํธ)์ ๋ฉ๋ชจ๋ฆฌ ์์ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ฒ ๋๋ฏ๋ก, ํด๋ผ์ด์ธํธ์ ๋ถ๋ด์ด ๋์ด๋๋ค. |
์ปดํฌ๋ํธ ์ธ๋ถ | ํด๋ผ์ด์ธํธ๊ฐ ํํฐ๋ง ๊ตฌํ ํ์X | ๋น๋ฒํ HTTP ์์ฒญ ์๋ฒ๊ฐ ํํฐ๋ง์ ์ฒ๋ฆฌํ๋ฏ๋ก ๋ถ๋ด์ ๊ฐ์ ธ๊ฐ๋ค. |
๐ฃ Ajax ์์ฒญ์ด ๋๋ฆด ๊ฒฝ์ฐ
โ๏ธ ์ธ๋ถ API ์ ์์ด ๋๋ฆด ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํด์, ๋ก๋ฉ ํ๋ฉด์ ๊ตฌํ์ ํ์์ ์ด๋ค.
const [isLoading, setIsLoading] = useState(true);
// ์๋ต, LoadingIndicator ์ปดํฌ๋ํธ๋ ๋ณ๋๋ก ๊ตฌํํ์์ ๊ฐ์ ํฉ๋๋ค
return {isLoading ? <LoadingIndicator /> : <div>๋ก๋ฉ ์๋ฃ ํ๋ฉด</div>}
useEffect(() => {
setIsLoading(true);
fetch(`http://์๋ฒ์ฃผ์/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
setIsLoading(false);
});
}, [filter]);
โฐ fetch ์์ฒญ ์ ํ๋ก setIsLoading์ ์ค์ ํด์ค๋ค.
'CodeStates > learning contents' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
S2) Unit 10. [Web Server] Refactor Express (0) | 2023.02.07 |
---|---|
S2) Unit 10. [Web Server] CORS (0) | 2023.02.06 |
S2) Unit 9. [React] React ๋ฐ์ดํฐ ํ๋ฆ (0) | 2023.02.02 |
S2) Unit 8. [HTTP/๋คํธ์ํฌ] Postman (0) | 2023.02.01 |
S2) Unit 8. [HTTP/๋คํธ์ํฌ] REST API (0) | 2023.01.31 |