[react] Effect Hook
Categories: react
๐ ๊ฐ์ธ์ ์ธ ๊ณต๊ฐ์ผ๋ก ๊ณต๋ถ๋ฅผ ๊ธฐ๋กํ๊ณ ๋ณต์ตํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ธ๋ก๊ทธ์
๋๋ค.
์ ํํ์ง ์์ ์ ๋ณด๊ฐ ์์ ์ ์์ผ๋ ์ฐธ๊ณ ๋ฐ๋๋๋ค :๐ธ
[ํ๋ฆฐ ๋ด์ฉ์ ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์๋ฉด ๋ณต๋ฐ์ผ์ค๊ฑฐ์์]
React์์๋ ์ปดํฌ๋ํธ ๋ด์์ fetch๋ฅผ ์ฌ์ฉํด API ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ด๋ฒคํธ๋ฅผ ํ์ฉํด DOM ์ง์ ์กฐ์ํ ๋ Side Effect๊ฐ ๋ฐ์ํ๋ค๊ณ ๋งํ๋ค.
Pure Function (์์ ํจ์)
- ์์ ํจ์๋, ์ค์ง ํจ์์ ์ ๋ ฅ๋ง์ด ํจ์์ ๊ฒฐ๊ณผ์ ์ํฅ์ ์ฃผ๋ ํจ์๋ฅผ ์๋ฏธํฉ๋๋ค
- ํจ์์ ์ ๋ ฅ์ด ์๋ ๋ค๋ฅธ ๊ฐ์ด ํจ์์ ๊ฒฐ๊ณผ์ ์ํฅ์ ๋ฏธ์น๋ ๊ฒฝ์ฐ, ์์ ํจ์๊ฐ ์๋๋ค.
- ์ ๋ ฅ์ผ๋ก ์ ๋ฌ๋ ๊ฐ์ ์์ ํ์ง ์๋๋ค.
- ์ฆ, ์ ๋ฌ ์ธ์๊ฐ ์ฃผ์ด์ง ๊ฒฝ์ฐ, ํญ์ ๋๊ฐ์ ๊ฐ์ด ๋ฆฌํด๋จ์ ๋ณด์ฅ (๊ณ ๋ก
Math.random()
์ ์์ ํจ์๊ฐ ์๋๋ค) - ์์ ํจ์์๋ ๋คํธ์ํฌ ์์ฒญ๊ณผ ๊ฐ์ Side Effect๊ฐ ์๋ค.
1
2
3
4
5
function upper(str) {
return str.toUpperCase(); // toUpperCase ๋ฉ์๋๋ ์๋ณธ์ ์์ ํ์ง ์์ต๋๋ค (Immutable)
}
upper('hello') // 'HELLO'
-
์ด๋ค ํจ์๊ฐ fetch API๋ฅผ ์ด์ฉํด AJAX ์์ฒญ์ ํ๋ค๊ณ ๊ฐ์ ํ์ ๋ ์ด ํจ์๋ ์์ ํจ์๊ฐ ์๋๋ค. ๊ทธ ์ด์ ๋?
โ ๋ฐํํ๋ ๊ฐ์ด ์ธ์ ๋ ๋์ผํ์ง ์๊ธฐ ๋๋ฌธ, ์ธ๋ถ์ ์ด๋ ํ ๊ฐ์ ์ฐธ์กฐ(ํธ์ถ)ํด์ผ ํด์ ๊ทธ ๊ฐ์ด ๋ฌ๋ผ์ง๋ฉด ๊ฒฐ๊ณผ๋ ๋ฌ๋ผ์ง๊ฒ ๋๊ธฐ ๋๋ฌธ.
React์ ํจ์ ์ปดํฌ๋ํธ
- React์ ํจ์ ์ปดํฌ๋ํธ๋, props๊ฐ ์ ๋ ฅ์ผ๋ก, JSX Element๊ฐ ์ถ๋ ฅ์ผ๋ก ๋๊ฐ๋ค.
- ์ฌ๊ธฐ์๋ ๊ทธ ์ด๋ค Side Effect๋ ์์ผ๋ฉฐ, ์์ ํจ์๋ก ์๋ํ๋ค.
1
2
3
4
5
6
7
function SingleTweet({ writer, body, createdAt }) {
return <div>
<div>{writer}</div>
<div>{createdAt}</div>
<div>{body}</div>
</div>
}
React ์ปดํฌ๋ํธ์์์ Side Effect
- ํ์ด๋จธ ์ฌ์ฉ (setTimeout)
- ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ (fetch API, localStorage)
ํ์ง๋ง ๋ณดํต React ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑํ ๋์๋, AJAX ์์ฒญ์ด ํ์ํ๊ฑฐ๋, LocalStorage ๋๋ ํ์ด๋จธ์ ๊ฐ์ React์ ์๊ด์๋ API๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ์ ์๊ณ ์ด๋ React์ ์ ์ฅ์์๋ ์ ๋ถ Side Effect์ ํด๋นํ๋ค..
React๋ Side Effect๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํ Hook์ธ Effect Hook์ ์ ๊ณตํฉ๋๋ค.
Effect Hook
useEffect
๋ ์ปดํฌ๋ํธ ๋ด์์ Side effect๋ฅผ ์คํํ ์ ์๊ฒ ํ๋ Hook- useEffect(ํจ์, [์ข ์์ฑ1, ์ข ์์ฑ2, โฆ])
useEffect
์ ์ฒซ ๋ฒ์งธ ์ธ์๋ ํจ์, ํด๋น ํจ์ ๋ด์์ side effect๋ฅผ ์คํํ๋ฉด ๋๋ค.useEffect
์ ๋ ๋ฒ์งธ ์ธ์๋ ๋ฐฐ์ด, ๋ฐฐ์ด์ ์กฐ๊ฑด์ ๋ด๊ณ ์๋ค. ์ฌ๊ธฐ์ ์กฐ๊ฑด์ boolean ํํ์ ํํ์์ด ์๋, ์ด๋ค ๊ฐ์ ๋ณ๊ฒฝ์ด ์ผ์ด๋ ๋๋ฅผ ์๋ฏธํ๋ค. ๋ฐ๋ผ์, ํด๋น ๋ฐฐ์ด์ ์ด๋ค ๊ฐ์ ๋ชฉ๋ก์ด ๋ค์ด๊ฐ๋๋ค. ์ด ๋ฐฐ์ด์ ํน๋ณํ ์ข ์์ฑ ๋ฐฐ์ด์ด๋ผ๊ณ ๋ ํ๋ค.- ๋น ๋ฐฐ์ด ๋ฃ๊ธฐ
useEffect(ํจ์, [])
: ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ์์ฑ๋ ๋๋ง effect ํจ์๊ฐ ์คํ - ์๋ฌด๊ฒ๋ ๋ฃ์ง ์๊ธฐ(๊ธฐ๋ณธ ํํ)
useEffect(ํจ์)
: ๊ธฐ๋ณธํํ,
- ๋น ๋ฐฐ์ด ๋ฃ๊ธฐ
์คํ๋๋ ์๊ธฐ
- ์ปดํฌ๋ํธ ์์ฑ ํ ์ฒ์ ํ๋ฉด์ ๋ ๋๋ง(ํ์)
- ์ปดํฌ๋ํธ์ ์๋ก์ด props๊ฐ ์ ๋ฌ๋๋ฉฐ ๋ ๋๋ง
- ์ปดํฌ๋ํธ์ ์ํ(state)๊ฐ ๋ฐ๋๋ฉฐ ๋ ๋๋ง
์ด์ ๊ฐ์ด ๋งค๋ฒ ์๋กญ๊ฒ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ๋ Effect Hook์ด ์คํ
Hook์ ์ธ ๋ ์ฃผ์ํ ์
- ์ต์์์์๋ง Hook์ ํธ์ถํฉ๋๋ค.
-
React ํจ์ ๋ด์์ Hook์ ํธ์ถํฉ๋๋ค.
https://ko.legacy.reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
์ปดํฌ๋ํธ ๋ด์์ AJAX ์์ฒญ
๋ชฉ๋ก ๋ด ํํฐ๋ง์ ๊ตฌํํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ๋ ๊ฐ์ง ์ ๊ทผ์ด ์์ ์ ์๋ค.
- ์ปดํฌ๋ํธ ๋ด์์ ํํฐ๋ง: ์ ์ฒด ๋ชฉ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๊ณ , ๋ชฉ๋ก์ ๊ฒ์์ด๋ก filter ํ๋ ๋ฐฉ๋ฒ
-
์ปดํฌ๋ํธ ์ธ๋ถ์์ ํํฐ๋ง: ์ปดํฌ๋ํธ ์ธ๋ถ๋ก API ์์ฒญ์ ํ ๋, ํํฐ๋งํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ค๋ ๋ฐฉ๋ฒ (๋ณดํต, ์๋ฒ์ ๋งค๋ฒ ๊ฒ์์ด์ ํจ๊ป ์์ฒญํ๋ ๊ฒฝ์ฐ๊ฐ ์ด์ ํด๋นํ๋ค.)
ย ์ฅ์ ๋จ์ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ฒ๋ฆฌ HTTP ์์ฒญ์ ๋น๋๋ฅผ ์ค์ผ ์ ์๋ค ๋ธ๋ผ์ฐ์ (ํด๋ผ์ด์ธํธ)์ ๋ฉ๋ชจ๋ฆฌ ์์ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ฒ ๋๋ฏ๋ก, ํด๋ผ์ด์ธํธ์ ๋ถ๋ด์ด ๋์ด๋๋ค ์ปดํฌ๋ํธ ์ธ๋ถ์์ ์ฒ๋ฆฌ ํด๋ผ์ด์ธํธ๊ฐ ํํฐ๋ง ๊ตฌํ์ ์๊ฐํ์ง ์์๋ ๋๋ค ๋น๋ฒํ HTTP ์์ฒญ์ด ์ผ์ด๋๊ฒ ๋๋ฉฐ, ์๋ฒ๊ฐ ํํฐ๋ง์ ์ฒ๋ฆฌํ๋ฏ๋ก ์๋ฒ๊ฐ ๋ถ๋ด์ ๊ฐ์ ธ๊ฐ๋ค
AJAX ์์ฒญ ๋ณด๋ด๊ธฐ
์์๋ก ๊ตฌํํ storageUtil.js ๋์ , fetch API๋ฅผ ์จ์ ์๋ฒ์ ์์ฒญํ ๋,
๋ช ์ธ์ ์ ๊ณตํ๋ API์ ์๋ํฌ์ธํธ๊ฐ http://์๋ฒ์ฃผ์/proverbs๋ผ๊ณ ๊ฐ์ ํ๋ฉด ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
1
2
3
4
5
6
7
useEffect(() => {
fetch(`http://์๋ฒ์ฃผ์/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
});
}, [filter]);
Loading indicator์ ๊ตฌํ
1
2
3
4
const [isLoading, setIsLoading] = useState(true);
// ์๋ต, LoadingIndicator ์ปดํฌ๋ํธ๋ ๋ณ๋๋ก ๊ตฌํํ์์ ๊ฐ์ ํฉ๋๋ค
return {isLoading ? <LoadingIndicator /> : <div>๋ก๋ฉ ์๋ฃ ํ๋ฉด</div>}
fetch ์์ฒญ์ ์ ํ๋ก setIsLoading
์ ์ค์ ํด ์ฃผ์ด ๋ณด๋ค ๋์ UX๋ฅผ ๊ตฌํํ ์ ์๋ค.
1
2
3
4
5
6
7
8
9
useEffect(() => {
setIsLoading(true);
fetch(`http://์๋ฒ์ฃผ์/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
setIsLoading(false);
});
}, [filter]);
Leave a comment