3. React Hooks
React Hook ์ด๋
Hooks
useState
useEffect
useContext
useRef
useLayoutEffect
React StrictMode ๋
๊ฐ์ ์ ๋ฆฌ
React์ Hook
(์ฌ์ํจ) ๋ณดํต ์ธ๊ตญ์์๋ ๋ณต์ํ์ผ๋ก ๋ง์ด ๋ถ๋ฅธ๋ค. Hooks, Github Actions. ํ๊ตญ์์๋ Hook, Github Action๊ณผ ๊ฐ์ด ๋จ์๋ก ๋ง์ด ํ๊ธฐํ๋ค.
React 16๋ถํฐ ์ฒด๊ณ๊ฐ ์กํ๋ค. React 16.8์์ Hooks๊ฐ ๋์ ๋์๋ค. React 18์์๋ Concurrent Mode๊ฐ ๊ฐ์กฐ๊ฐ ๋์๋ค.
๋ฆฌ์กํธ์์ ์ฌ์ฉํ๋ ๊ธฐ์กด ๋ฐฉ์์ ๋ฌธ์ ๊ฐ ์์๋ค.
Wrapper Hell (HoC), ์ฅํ์ ์๊ฒ ๋๋ค.
Huge Components
Confusing Classes, ๋ํดํ this
Class Component๋ฅผ ์ฌ์ฉํ์ง๋ง, ๊ฐ์ฒด์งํฅ์ผ๋ก ์ง๋๊ฒ๋ ์๋๋ค. ํผ๋์ค๋ฌ์ด ๋ฉด์ด ์์๋ค. Class Component๋ฅผ ์์ ๊ฒ ๋ค๋ ๊ฒ์ ์๋์ง๋ง, Function Component์ Hook์ ์ฌ์ฉํ ๊ฒ์ด๋ผ๋ ๋ง. ๊ธฐ์กด์ Class ์ฝ๋๋ ๋ฌธ์ ์์ด ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
์์ ์๋ ์ํ๋ฅผ ๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ Class Component๋ก ๋ง๋ค๊ณ props๋ง ์ฌ์ฌ์ฉ ํ๋ ์์ํ ์ปดํฌ๋ํธ๋ Function Component๋ก ์์ฑํ๋ค. Redux์์๋ Presentational, Container Components๋ก ๋ถ๋ฆฌํ๋ค.
์ด์ ๋ ๋ชจ๋ Function Component๋ก ์ฌ์ฉํ๋ค. ๋๋ฉ์ธ ๋ก์ง๋ค์ ๋ชจ๋ ์ปค์คํ ํ ์ผ๋ก ๋ถ๋ฆฌํ์ฌ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
๋ํ์ ์ธ Hooks
useState -> State Hook -> React์ State
useEffect -> Side-effect
useContext
useRef
useLayoutEffect -> useEffect์ ๊ฐ๊ฒ ๋์ํ์ง๋ง ์คํ ์์ ์ด ๋ค๋ฅด๋ค.
useEffect
๋ฆฌ์กํธ ๋ฒ ํ ๋ฌธ์์ You Might Not Need an Effect
๋ผ๋ ์ฃผ์ ์ ๋ด์ฉ๋ ์๋ฏ์ด useEffect๋ฅผ ์ ๋๋ก ์ฌ์ฉํ๋๊ฒ ์ค์ํ๋ค.
useEffect๋ ๋ ๋๋ง ์ดํ์ ํด์ผ ํ ์ผ, React์ ์ธ๋ถ์ ๊ด๋ จ๋ ์ผ์ ์ ํด์ค ์ ์๋ค.
ํ์ด๋จธ ์์
// ๋ธ๋ผ์ฐ์ ์ title์ ๋ฐ๋ฆฌ์ด๋ก ๋ณ๊ฒฝํ๋ค.
useEffect(() => {
document.title = `Now: ${new Date().getTime()}`;
});
function Timer() {
useEffect(() => {
const savedTitle = document.title;
// useEffect ๋ด๋ถ์์ setTimeout, setInterval์ ์ฌ์ฉํ ๊ฒฝ์ฐ์๋ ์ปดํฌ๋ํธ๊ฐ unmount ๋์์ ๋ clear๋ฅผ ํด์ค์ผ ํ๋ค.
// useEffect์ clean up ํจ์๋ฅผ ์ด์ฉํด์ ์ฒ๋ฆฌํ๋ค.
const id = setInterval(() => {
document.title = `Now: ${new Date().getTime()}`;
}, 100);
return () => {
document.title = savedTitle;
clearInterval(id);
};
});
return <p>Playing</p>;
}
export default function TimerControl() {
const [playing, setPlaying] = useState(false);
const handleClick = () => {
setPlaying(!playing);
};
return (
<div>
{playing ? <Timer /> : <p>Stop</p>}
<button type="button" onClick={handleClick}>
Toggle
</button>
</div>
);
}
์ฒ์์ ํ๋ฒ๋ง ์คํํ๊ธฐ
useEffect์ 2๋ฒ์งธ ๋งค๊ฐ๋ณ์์ ์์กด์ฑ ๋ฐฐ์ด์ ๋ฃ์ด์ค ์ ์๋ค.
๋น ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด, ์ปดํฌ๋ํธ๊ฐ ์ฒ์ mount๋ ๋๋ง useEffect์ setup function์ด ์คํ๋๋ค.
ํน์ ๊ฐ์ ๋ด๊ณ ์๋ ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด, ์ปดํฌ๋ํธ๊ฐ ์ฒ์ mount๋ ๋์, ํน์ ๊ฐ์ด ๋ณ๊ฒฝ๋์์ ๋๋ง useEffect์ setup function์ด ์คํ๋๋ค.
๋ฐฐ์ด์ ๋ฃ์ด์ฃผ์ง ์์ผ๋ฉด, ์ปดํฌ๋ํธ๊ฐ ์ฒ์ mount๋ ๋์, ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง์ด ๋ ๋๋ง๋ค setup function์ด ์คํ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก๋ data fetching์ ํ ๋ useEffect๋ฅผ ์ฌ์ฉํ๋ค.
const [products, setProducts] = useState<Product[]>([]);
useEffect(() => {
const fetchProducts = async () => {
const url = 'http://localhost:3000/products';
const response = await fetch(url);
const data = await response.json();
setProducts(data.products);
};
fetchProducts();
}, []);
fetchProducts๋ผ๋ ํจ์๊ฐ useEffect ๋ด๋ถ์ ์์ด์ผ ํ๋์ง์ ๋ํ ์๋ฌธ์ด ์์ ์ ์๋ค. ์ค์ ๋ก useEffect ์ธ๋ถ์, ์ปดํฌ๋ํธ ๋ด๋ถ์ ์ ์ธํด๋ ๋ฌธ์ ๋ ์๋ค. ํ์ง๋ง fetchProducts ๋ด๋ถ์์ Component์ State๊ฐ์ ์ฐธ์กฐํ๋ ๊ฒฝ์ฐ์๋ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค. Component๊ฐ ๋ ๋๋ง์ด ๋์์ ๋ ๋ฐ๊นฅ์ ์๋ ๋ณ์๋ค์ ์บก์ฒํด์ ์ฐ๊ธฐ ๋๋ฌธ์(๋ฐ์ธ๋ฉ) ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค. ๊ฐ๋ฅํ๋ฉด ํจ์๋ค์ useEffect ๋ด๋ถ์ ๋ชจ๋ ๋ฃ์ผ๋ฉด ๊ณ ๋ฏผํ ํ์๊ฐ ์๋ค. useEffect์ setup function์ด ํด๋ก์ ๊ฐ ๋๋ค.
Effect๊ฐ ๋ ๋ฒ ์คํ๋๋ ๋ฌธ์
StrictMode๋ ๊ฐ๋ฐ์๊ฐ ์ผ์ผํฌ ์ ์๋ ๋ฌธ์ ๋ฅผ ๊ฒ์ฌํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค. dev ํ๊ฒฝ์์ ๋ ๋๋ง์ด 2๋ฒ ๋๋๊ฒ์ ๋ฌธ์ ๊ฐ ์๋๋ค. ๊ฐํน useEffect์์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ, flag ๋ณ์๋ฅผ ์ด์ฉํ๋ค.
์์กด์ฑ ๋ฐฐ์ด์ ์ด์ฉํด Fetchํ ๋ ์ฃผ์์ฌํญ
๋ฆฌ์กํธ์์๋ ์ปดํฌ๋ํธ๊ฐ unmount ๋์์ ๋ ์ํ๋ฅผ ์ ๋ฐ์ดํธ ํ๋ ค๊ณ ํ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธด๋ค. ์ด๋ฅผ ๋ง๊ธฐ์ํด flag ๋ณ์๋ฅผ ์ด์ฉํ์ฌ data fetching์ด ์๋ฃ๋์์ ๋ ์ปดํฌ๋ํธ๊ฐ unmount๋์ง ์์์ผ๋ฉด setter function์ ์คํํ๋๋ก ํ๋ค. axios๋ฅผ ์ด์ฉํ๋ ๊ฒฝ์ฐ์ ๊ธฐ์กด์๋ cancelToken์ ์ฌ์ฉํ๋๋ฐ ์ด์ ๋ deprecated ๋์๊ณ AbortController๋ฅผ ์ฌ์ฉํ๋๊ฒ์ด ๊ถ์ฅ๋๋ค.
Last updated