15.1 ์ปค์คํ
ํ
(Custom Hook)์ด๋?15.2 ์ปค์คํ
ํ
์ฃผ์์ฌํญ15.2.1 ์ฃผ์์ฌํญ15.2.2 ๊ณ ๋ ค์ฌํญ15.3 ์ปค์คํ
ํ
์ฌ์ฉํด๋ณด๊ธฐ15.3.1 ์ปค์คํ
ํ
์ฌ์ฉ๋ฐฉ๋ฒ 15.3.2 ๊ฐ๋จํ ์ปค์คํ
ํ
๋ง๋ค์ด๋ณด๊ธฐ 15.4 (์ค์ต1) useTitle 15.4.1 Document Title15.4.2 useTitle ์ ์ฉํ๊ธฐ15.5 (์ค์ต2) useClick15.5.1 useClick Hook ์ด๋?15.5.2 useClick์ ์ ์ฌ์ฉํ ๊น์?15.5.3 useClick ์ ์ฉํ๊ธฐ15.6 (์ค์ต3) useToggle 15.6.1 useToggle Hook์ด๋?15.6.2 useToggle ์ ์ฉํ๊ธฐ15.6.3 (์์ 1) useToggle Hook์ ํ์ฉํ์ฌ ์ฒดํฌ๋ฐ์ค ๋ง๋ค๊ธฐ15.6.4 (์์ 2) useToggle Hook์ ํ์ฉํ์ฌ ๋ฆฌ์คํธ ์ถ๋ ฅํ๊ธฐ15.7 (์ค์ต4) useAxios 15.7.1 axios๋?15.7.2 axios ์์ฒญ15.7.3 useAxios ์ ์ฉํ๊ธฐ
15.1 ์ปค์คํ ํ (Custom Hook)์ด๋?
์ปค์คํ
ํ
์ ๋ฆฌ์กํธ ์ ํ๋ฆฌ์ผ์ด์
์ ํจ์ ์ปดํฌ๋ํธ ๋ด ํน์ ๋ก์ง์ ๋ถ๋ฆฌํ ํจ์๋ก, ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํจ์์
๋๋ค. ์ปค์คํ
ํ
์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์ฝ๋๋ฅผ ์์ฑํ ๋ ํน์ ๋ก์ง์ ํจ์๋ก ๋ถ๋ฆฌํ๊ณ ์ฌ์ฌ์ฉํด ๋ถํ์ํ ์ฝ๋ ๋ฐ๋ณต์ ์ค์ด๋ ๊ฒ๊ณผ ๋น์ทํ ๋งฅ๋ฝ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
ย
์ปค์คํ
ํ
์ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ฌ๋ฌ ํจ์ ์ปดํฌ๋ํธ์์ ๊ณตํต์ผ๋ก ์ฌ์ฉ๋๋ ํน์ ์ปดํฌ๋ํธ ๋ก์ง์ ๋ถ๋ฆฌํด ํ์ํ ์ปดํฌ๋ํธ์์ ํธ์ถํ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ๋ณต๋๋ ์ฝ๋๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.
- ๋ฆฌ์กํธ ํ๋ก์ ํธ์์ ํน์ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํด ํ์์ ๋ฐ๋ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋์ ํ๊ธฐ๋ ํฉ๋๋ค. ํ์ง๋ง ์ํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ์ ์ ํฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ ๊ฒฝ์ฐ ์ปค์คํ ํ ์ ์ง์ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
ย
์ปค์คํ
ํ
์ ์ฅ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ฌ์ฌ์ฉ์ฑ
์ปค์คํ
ํ
์ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ํจ์ ์ปดํฌ๋ํธ์์ ์ค๋ณต๋๋ ๋ก์ง์ ๊ณต์ ํ ์ ์์ต๋๋ค. ์ฆ, ๋ก์ง์ ์ฌ์ฌ์ฉ์ฑ์ด ๋์ต๋๋ค.
ย
- ๊ฐ๋ ์ฑ
์ปค์คํ
ํ
์ ์ฌ์ฉํ๋ฉด ์ปค์คํ
ํ
์ ๋ด๋ถ ๋ก์ง์ ์ ํํ ๋ชฐ๋ผ๋ ์ด๋ค ๊ฐ์ด ๋ค์ด๊ฐ์ ์ด๋ค ๊ฒฐ๊ณผ๊ฐ์ด ๋ฐํ๋๋์ง๊ฐ ๋ช
ํํ๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค.
ย
fetch
๋ฅผ ์ฌ์ฉํด ๋น๋๊ธฐ ํต์ ์ ํ๋ useFetch
์ปค์คํ
ํ
์ ๋ง๋ค์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. useFetch
์ ์ ํํ ๋ก์ง์ ๋ชฐ๋ผ๋ ๋จ ํ์ค์ ์ฝ๋๋ก useFetch
๊ฐ ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ url์ ์ ๋ฌ๋ฐ์ ๋น๋๊ธฐ ํต์ ํ ๋ฐ์ ์๋ต ๋ฐ์ดํฐ, ๋ก๋ฉ ์ํ, ์๋ฌ๋ฅผ ๋ฐํํ๋ค๋ ๊ฒ์ ์ ์ถํ ์ ์์ต๋๋ค.ย
function App() { const url = "https://example.com/todos"; const {data: todos, isLoading, error} = useFetch(url); if (error) { return <div>{error}๊ฐ ๋ฐ์ํ์ต๋๋ค.</div>; } if (isLoading) { return <div>๋ก๋ฉ์ค์ ๋๋ค..</div>; } return <TodoList todos={todos} />; } export default App;
ย
์ง๊ธ๊น์ง ์ฑ
์์ ์๊ฐ๋ ๋ฆฌ์กํธ์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ํ
๊ณผ ์ถ๊ฐ์ ์ธ ํ
๋ค์ ํ์ฉํด ์ฌ๋ฌ๋ถ์ด ์ํ๋ ์ปค์คํ
ํ
์ ๊ตฌํํ ์ ์์ต๋๋ค. ๋ค์ ์ฑํฐ์์๋ ์ปค์คํ
ํ
์ฌ์ฉ ์ ์ฃผ์ํ ์ ๊ณผ ์ฌ์ฉ๋ฐฉ๋ฒ์ ์๊ฐํ๊ณ , ๋ฆฌ์กํธ์ ๋ด์ฅ๋ ํ
๋ค์ ํ์ฉํ ๋ค์ํ ์ปค์คํ
ํ
์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
ย
15.2 ์ปค์คํ ํ ์ฃผ์์ฌํญ
15.2.1 ์ฃผ์์ฌํญ
ย
์ปค์คํ
ํ
๋ Hook์ด๊ธฐ ๋๋ฌธ์ ์ฑ
์ ์ด๋ฐ๋ถ์ ๋ค๋ฃจ์๋ Hook์ ๊ท์น์ ๋ฐ๋ฆ
๋๋ค.
- ์ต์์(at the Top Level)์์๋ง Hook์ ํธ์ถํด์ผ ํฉ๋๋ค.
- ์ค์ง React ํจ์ ๋ด์์ Hook์ ํธ์ถํด์ผ ํฉ๋๋ค.
- Hook์ use๋ก ์์ํด์ผํ๋ ๊ท์น์ด ์์ต๋๋ค.
ย
15.2.2 ๊ณ ๋ ค์ฌํญ
ย
- ์ปค์คํ ํ ์ด ๊ผญ ํ์ํ์ง ํ์ธํด๋ด ์๋ค.
์ฌ์ฌ์ฉ๋ ๋ถ๋ถ์ด ๋ง์ง ์์๋ฐ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ๋ค๋ฉด ์ฝ๋๋ฅผ ํ๋์ ์ดํดํ๊ธฐ ํ๋ค ์ ์์ต๋๋ค. ๊ผญ ํ์ํ์ง ์๋ค๋ฉด ์ปค์คํ
ํ
์ผ๋ก ๋ถ๋ฆฌํ์ง ์๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์
๋๋ค.
ย
- ์ปค์คํ ํ ์ ์ด๋ฆ์ด ์ง๊ด์ ์ธ์ง ์๊ฐํด๋ด ์๋ค.
Hook์ ์ ์ธ์ ์ผ๋ก ์์ฑํด์ผ ํฉ๋๋ค. ์ ์ธ์ ์ด๋ผ๋ ๊ฒ์ ์ด๋ค ๋ฐฉ๋ฒ(HOW)์ผ๋ก ํด๊ฒฐํ ์ง๋ณด๋ค๋ ๋ฌด์(WHAT)์ ํด์ผ ํ ์ง๋ฅผ ๋ํ๋ธ๋ค๊ณ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ปค์คํ
ํ
์ผ๋ก ๋ง๋ค์ด์ง
useToggle
์ ๋ฌด์์ ์ฐ์ผ์ง ์์ํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ โ์ด๋ป๊ฒโ๋ผ๋ ๋ฐฉ๋ฒ๋ณด๋ค๋ โ๋ฌด์โ์ ํ๊ธฐ ์ํด ๋ง๋ค์ด์ง Hook์ธ์ง ์ ์ ์์ด์ผํฉ๋๋ค.ย
- ๋ง๋ค์ด์ง ์ปค์คํ ํ ์ด ์์ํ์ง ํ์ธํด๋ด ์๋ค.
์ฐ๋ฆฌ๊ฐ ์ ์ธ์ ์ผ๋ก ๋ง๋ ์ปค์คํ
ํ
์ด ์์ํ ๋๋ก ๋์ํ๊ธฐ ์ํด์ ์์ํด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ ์์ํ๋ค๋ ๊ฒ์, ๊ฐ์ ์ธ์๋ฅผ ๋ฃ์์ ๋ ๊ฐ์ ๋์์ ๊ธฐ๋ํ ์ ์๋ค๋ ์๋ฏธ์
๋๋ค. ๋ํ Hook์ด ์ฌ์ฉ๋๋ฉด์ ์ผ์ด๋ ์ ์๋ ์ฌ์ด๋์ดํํธ(Side Effect)๋ฅผ ์ต์ํํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์๋ค๋ฉด Hook์ ์ฌ์ฉํ ๋ ํญ์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ฅ๋ดํ ์ ์๊ณ ์ฌ์ด๋์ดํํธ๋ฅผ ์์ธกํ ์ ์์ด ์ ์ง๋ณด์๊ฐ ํ๋ค์ด์ง ๊ฒ์
๋๋ค.
์ฌ์ด๋์ดํํธ(Side Effect)
์ปดํจํฐ ๊ณผํ์์ย ํจ์๊ฐ ๊ฒฐ๊ณผ๊ฐ ์ด์ธ์ ๋ค๋ฅธ ์ํ๋ฅผ ๋ณ๊ฒฝ์ํฌ ๋ย ์ฌ์ด๋์ดํํธ ๋๋ ๋ถ์์ฉ์ด ์๋ค๊ณ ๋งํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํจ์๊ฐย ์ ์ญ๋ณ์๋ย ์ ์ ๋ณ์๋ฅผ ์์ ํ๊ฑฐ๋, ์ธ์๋ก ๋์ด์จ ๊ฒ๋ค ์ค ํ๋๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ํ๋ฉด์ด๋ ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ฑฐ๋, ๋ค๋ฅธ ๋ถ์์ฉ์ด ์๋ ํจ์์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ค๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ์ฌ์ด๋์ดํํธ๋ ํ๋ก๊ทธ๋จ์ ๋์์ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค.
ย
15.3 ์ปค์คํ ํ ์ฌ์ฉํด๋ณด๊ธฐ
15.3.1 ์ปค์คํ ํ ์ฌ์ฉ๋ฐฉ๋ฒ
ย
์๋ ์ฝ๋ ์์๋ ์์์ ์ฌ์ฉ๋
useFetch
์ปค์คํ
ํ
์
๋๋ค. import { useState, useEffect } from 'react'; const useFetch = url => { const [data, setData] = useState(null); useEffect(() => { fetch(url) .then(res => res.json()) .then(data => setData(data)) }, [url]); return [data]; }; export default useFetch;
ย
์ ์ฝ๋๋ ๋งค๋ฒ fetch๋ฅผ ํตํด ์๋ฒ์ ๋คํธ์ํฌ ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ก์ด ์ ๋ณด๋ฅผ ๋ฐ์์ค๋ ๊ฒฝ์ฐ ๋ฐ๋ณต๋๋ ์ฝ๋๋ฅผ ์ต์ํํ๊ธฐ ์ํด
useFetch
๋ผ๋ ์ปค์คํ
ํ
์ ๋ง๋ค์ด ์ฝ๋ ๋ก์ง์ ํจ์จ์ฑ์ ๋์ผ ์ ์์ต๋๋ค. ์ ์ฝ๋์์ ์ ์ ์๋ค์ํผ ์ฌ์ฉ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ย
์ฌ์ฉ๋ฐฉ๋ฒ
- ์ปค์คํ
ํ
์ ์ด๋ฆ์
use
๋ก ์์๋์ด์ผ ํฉ๋๋ค.
use
๋ก ์์๋์ง ์์ผ๋ฉด ํน์ ํ ํจ์๊ฐ ๊ทธ ์์์ Hook์ ํธ์ถํ๋์ง ์ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ฆฌ์กํธ ๊ณต์ ํํ์ด์ง์์ ๊ฐ์กฐํ๋ ๊ด์ต์ผ๋ก์จ ์ด๋ฅผ ๋ฐ๋ฅด์ง ์์ผ๋ฉด ํน์ ํ ํจ์๊ฐ ๊ทธ ์์์ Hook์ ํธ์ถํ๋์ง๋ฅผ ์ ์ ์๊ธฐ ๋๋ฌธ์ Hook ๊ท์น์ ์๋ฐ ์ฌ๋ถ๋ฅผ ์๋์ผ๋ก ์ฒดํฌํ ์ ์์ต๋๋ค.
ย
- ์ปค์คํ ํ ๋ํ useState์ useEffect๊ณผ ๊ฐ์ ๋ด์ฅ ํ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋
useFetch
์ ์ง์ ํธ์ถํ๊ธฐ ๋๋ฌธ์ ๋ฆฌ์กํธ ๊ด์ ์์ ์ปดํฌ๋ํธ๋ useState์ useEffect๋ง ํธ์ถํฉ๋๋ค. ํ๋์ ์ปดํฌ๋ํธ์์ ๋
๋ฆฝ์ ์ธ useState์ useEffect๋ฅผ ์ฌ๋ฌ ๋ฒ ํธ์ถํ ์ ์์ต๋๋ค. ย
- ๊ฐ์ ์ปค์คํ ํ ์ ์ฌ์ฉํ๋ ์๋ก ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ state๋ฅผ ๊ณต์ ํ์ง ์์ต๋๋ค.
์ปค์คํ
ํ
์ ์ํ ๊ด๋ จ ๋ก์ง์ ์ฌ์ฌ์ฉํ๋ ๋งค์ปค๋์ฆ์ด์ง๋ง ์ปค์คํ
ํ
์ ์ฌ์ฉํ ๋๋ง๋ค ๊ทธ ์์ state์ effect๋ ์์ ํ ๋
๋ฆฝ์ ์ด๊ธฐ ๋๋ฌธ์ ์๋ก ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ ๋
๋ฆฝ๋ state๋ฅผ ์ป์ ์ ์์ต๋๋ค.
ย
15.3.2 ๊ฐ๋จํ ์ปค์คํ ํ ๋ง๋ค์ด๋ณด๊ธฐ
ย
๋ค์ํ ์ปค์คํ
ํ
์ ๋ง๋ค์ด๋ณด๊ธฐ ์ ์ ๊ฐ๋จํ ์์์ ํจ๊ป ์ปค์คํ
ํ
์ฌ์ฉ ์ ๊ณผ ํ๋ฅผ ๋น๊ตํด๋ณด๋ฉฐ ์ฌ์ฉ ์ด์ ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
ย
import { useState } from "react"; function App() { const [value, setValue] = useState(""); const handleChange = (e) => { setValue(e.target.value); }; return ( <div> <p>{value}</p> <input type="text" onChange={handleChange} /> </div> ); } export default App;
ย
ย
์ ์ฝ๋๋ useState๋ฅผ ํตํด ์ฌ์ฉ์์ ์
๋ ฅ๊ฐ์ ๋ฐ๋ผ ํด๋น ๊ฐ์ ์ถ๋ ฅํด์ฃผ๋ ์ฝ๋์
๋๋ค. input ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค handleChange ํจ์๋ฅผ ์คํ์์ผ state๋ฅผ ์
๋ฐ์ดํธํ๊ฒ ๋ฉ๋๋ค. ํ์ฌ๋ ํ๋์ input ๊ฐ๋ง ์ฒ๋ฆฌํ๊ณ ์๊ธฐ ๋๋ฌธ์ ํ๋์ ํจ์๋ก ์ถฉ๋ถํ์ง๋ง, ๋ง์ฝ ์ฌ๋ฌ ๊ฐ์ input ๊ฐ์ ์ฒ๋ฆฌํด์ผ ํ๋ค๋ฉด ์ค๋ณต๋๋ ์ฝ๋๊ฐ ๋์ด๋ ๊ฒ์
๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด input ๊ฐ์ ์ฒ๋ฆฌํ๋
useInput
์ด๋ผ๋ ์ปค์คํ
ํ
์ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.ย
import { useState } from "react"; export const useInput = (initialValue) => { const [value, setValue] = useState(initialValue); // --- โต const handleChange = (e) => { setValue(e.target.value); }; return [value, handleChange]; // --- โถ };
ย
App.jsx์์ state๋ฅผ ์
๋ฐ์ดํธํ๋ ํจ์๋ฅผ useInput.js๋ก ์ฎ๊ฒจ์ฃผ์์ต๋๋ค. โต์์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ๊ฐ์ธ initialValue๋ฅผ useState์ ์ด๊น๊ฐ์ผ๋ก ์ค์ ํ์์ต๋๋ค. ๋ง์ฝ ์ด๊น๊ฐ์ ์ง์ ํ ํ์๊ฐ ์๋ค๋ฉด ๋งค๊ฐ๋ณ์๋ฅผ ์ง์ ํ์ง ์๊ณ ์ฌ์ฉํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค. โถ์์ ๋ฐํ๊ฐ์ ๋ฐฐ์ด๋ก ์ค์ ํ์ฌ value์ state์ handleChange ํจ์๋ฅผ ๋ฐํํ๋๋ก ํ์์ต๋๋ค.
ย
import { useInput } from "./useInput"; function App() { const [value, handleChange] = useInput("์๋ ๋ผ์ด์บฃ๐ฆ"); // --- โต return ( <div> <p>{value}</p> <input type="text" value={value} onChange={handleChange} /> // --- โถ </div> ); } export default App;
ย
ย
๋ง๋ค์ด๋์
useInput
์ปค์คํ
ํ
์ App.jsx์์ ์ฌ์ฉํ๊ธฐ ์ํด import ํฉ๋๋ค. โต์์ useInput
์์ ๋ฐํํ๋ ๊ฐ์ ๋ฐฐ์ด๋ก ๋ฐ์์ค๊ณ , ์ธ์๋ก โ์๋
๋ผ์ด์บฃ๐ฆโ์ ์ด๊น๊ฐ์ผ๋ก ์ค์ ํ์์ต๋๋ค. input์ ๋ฐ์์จ value์ handleChange ํจ์๋ฅผ ์ค์ ํ ๊ฒ์ โถ์์ ํ์ธํ ์ ์์ต๋๋ค. ์คํํด๋ณด๋ฉด ์ด๊น๊ฐ์ด ์ ์ฉ๋ ๊ฒ๊ณผ ์
๋ ฅ๊ฐ์ ๋ฐ๋ผ ์ถ๋ ฅ๊ฐ์ด ๋ณ๊ฒฝ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.ย
๋ง์ฝ ํ๋์ ์ปดํฌ๋ํธ์ ์ฌ๋ฌ ๊ฐ์ input์ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ ์ฉํ ์ ์์ต๋๋ค.
ย
import { useInput } from "./useInput"; function App() { const [value, handleChange] = useInput("์๋ ๋ผ์ด์บฃ๐ฆ"); const [value2, handleChange2] = useInput(""); // --- โต return ( <div> <p>{value}</p> <input type="text" value={value} onChange={handleChange} /> <p>{value2}</p> <input type="text" onChange={handleChange2} /> // --- โถ </div> ); } export default App;
ย
ย
์ ์์ ์์ ๋ง๋ input ์๋์ ์ด๊น๊ฐ์ ์ง์ ํ์ง ์์ input์ ํ๋ ๋ ์ถ๊ฐํด๋ณด๊ฒ ์ต๋๋ค. โต์์๋ ์์์ ๋ง๋ input์ด ๋ฐ๋ ๋ณ์์ ๋ค๋ฅธ ๋ณ์๋ช
์ผ๋ก ์ง์ ํ์ฌ
useInput
์ ๋ฐํ๊ฐ์ ๋ฐ์์์ต๋๋ค. ์คํํด๋ณด๋ฉด ๋ ๊ฐ์ input์ด ๊ฐ๊ฐ ์ฒ๋ฆฌ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด์ฒ๋ผ ์ฌ๋ฌ ๊ฐ์ ์ปดํฌ๋ํธ ๋๋ ํ๋์ ์ปดํฌ๋ํธ์์ useInput
์ ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉํ๋๋ผ๋ ๋ชจ๋ input์ ๋
๋ฆฝ์ ์ธ state๋ฅผ ๊ฐ์ง๊ฒ ๋๋ฉฐ, ๊ฐํธํ๊ฒ ์ฌ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค. ย
์ปค์คํ
ํ
์ฌ์ฉ ์ ํ๋ฅผ ์ดํด๋ด์ผ๋ก์จ ์ฐ๋ฆฌ๋ ์ปค์คํ
ํ
์ ํตํด ์ค๋ณต๋๋ ์ฝ๋๊ฐ ๋์ด๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ฉฐ, ํ์ํ ๋ถ๋ถ์ ๊ฐํธํ๊ฒ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์ ์ ์์์ต๋๋ค. ์ด์ ๋ค์ํ ์ปค์คํ
ํ
์ ์ง์ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
ย
15.4 (์ค์ต1) useTitle
ย
15.4.1 Document Title
ย
Document Title
์น ์ฌ์ดํธ์ ์ ์ํ๋ฉด ๋ธ๋ผ์ฐ์ ์ ์๋จ ํญ์์ ํ์ฌ ํ์ด์ง์ ์ ๋ชฉ์ ๋ณผ ์ ์์ผ๋ฉฐ ํด๋น ํ์ด์ง์ ์ ๋ชฉ์ Document Title์ด๋ผ๊ณ ํฉ๋๋ค. Document Title์ ๊ฐ์ฅ ๋ํ์ ์ธ ์น ํ์ด์ง์ ํ์ดํ๋ก, ๊ฐ ํ์ด์ง์ ์ฃผ์ ๋ฅผ ๊ฐ์ฅ ์ ๋ํ๋ผ ์ ์๋ ์์์ด์ ํด๋น ์น ํ์ด์ง๋ฅผ ์ฌ์ฉํ๋ ์ ์ ์๊ฒ ํ์ฌ ์์ ์ด ๋ณด๊ณ ์๋ ์น ํ์ด์ง๊ฐ ์ด๋ค ํ์ด์ง์ธ์ง๋ฅผ ์๋ ค์ฃผ๋ ์ค์ํ ์์์
๋๋ค.
ย
ย
ํ์ง๋ง React๋ SPA์ด๋ฏ๋ก CSS, JS ๋ฑ์ ๋ฒ๋ค์ด ํฌํจ๋ ํ๋์ index.html ํ์ผ๋ง ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ๊ฐ ํ์ด์ง๋ง๋ค Document Title์ ๋ณ๊ฒฝํ๋๋ฐ ํ๊ณ์ ์ด ์์ต๋๋ค. ์ด๋ฅผ ์ํด ํ์ฌ ํ์ด์ง์ title์ ๋ฐ๊ฟ์ฃผ๊ธฐ ์ํ useTitle ์ปค์คํ
ํ
์ ํ์ฉํ๋ค๋ฉด ํ์ด์ง๋ง๋ค Document Title์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
ย
15.4.2 useTitle ์ ์ฉํ๊ธฐ
ย
import { useEffect } from 'react'; const useTitle = (title) => { useEffect(() => { const prevTitle = document.title; document.title = title; return () => (document.title = prevTitle); }, [title]); }; export default useTitle;
ย
useTitle์ title์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ ๋ฐ๋ ์ปค์คํ
ํ
์
๋๋ค. ์๋ก์ด ์ปดํฌ๋ํธ๊ฐ mount ๋๊ณ , ํด๋น ์ปดํฌ๋ํธ์์ useTitle์ ํธ์ถํ๋ ๋์์ ๋ณ๊ฒฝํ๊ณ ์ ํ๋ title์ ์ ๋ฌํ๋ฉด, useTitle ๋ด๋ถ์ useEffect์์๋ title์ด ๋ณ๊ฒฝ๋์์ผ๋ฏ๋ก ๋ด๋ถ์ ์ฝ๋๋ฅผ ์คํ์ํต๋๋ค. useEffect ๋ด๋ถ์์๋ Document Title์ ์
๋ ฅ ๋ฐ์ title๋ก ๋ณ๊ฒฝํ๊ณ , ํด๋น ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ผ์ง ๋ ๋์ํ Document Title์ ์๋๋๋ก ๋๋ ค๋๊ธฐ ์ํ cleanup ํจ์๋ฅผ ๋ฐํํฉ๋๋ค.
ย
import useTitle from './useTitle'; function Login() { useTitle('Login - React'); return <div>Login ํ์ด์ง</div> } export default Login;
ย
ย
๊ทธ๋ฆฌ๊ณ ์ ์ฝ๋์ฒ๋ผ useTitle ์ปค์คํ
ํ
์ Login ์ปดํฌ๋ํธ์ ์ ์ฉํ๋ฉด Login ํ์ด์ง๋ฅผ ๋ก๋ํ์ ๋ Document Title์ด โLogin - Reactโ๋ก ๋ณ๊ฒฝ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
๋ํ, Document Title์ ์ค์ ํ ๋์๋ ์ฌ์ฉ์๊ฐ ์ด๋ ์ฌ์ดํธ์ ์ ์ํ ๊ฒ์ธ์ง๋ ์ธ์งํ๊ณ ์๋ ์ํ์ด๋ฏ๋ก Login ํ์ด์ง์ฒ๋ผ ์๋ธ ํ์ด์ง ์ด๋ฆ์ด ์์ ๋์ค๋ ๊ฒ์ด ์ฌ์ฉ์ ํผ๋ก๋๋ฅผ ๋ฎ์ถ ์ ์์ต๋๋ค.
ย
15.5 (์ค์ต2) useClick
ย
์์ 8.1 useRef ์์ useRef๋ย .current ํ๋กํผํฐ์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ฐ์ ๋ด๊ณ ์๋ โ์์โ ์
๊ฐ๋ค๋ ๊ฒ์ ๋ฐฐ์ ์ต๋๋ค. ํน์ DOM์ ์ ๊ทผํด์ ์ ์ดํ๊ฑฐ๋, ๋ ๋๋ง๊ณผ ๊ด๊ณ์์ด ๊ฐ์ ๋ณ๊ฒฝํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ํ
์ด์๋๋ฐ์. useClick ์ปค์คํ
ํ
์ ๋ง๋ค ๋ ๊ฐ์ฅ ํ์ํ ํ
์
๋๋ค.
๋๋ถ์ด useEffect ๋ํ ์ฒซ ๋ ๋๋ง์ด ๋์์ ๋์ ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ ๋์์ ๋ ์ด๋ฒคํธ๋ฅผ ์ถ๊ฐ, ์ญ์ ํด์ค์ผํ๋ฏ๋ก useClick ์ปค์คํ
ํ
์์ ๋งค์ฐ ์ค์ํ ํ
์ด๋ผ ํ ์ ์๊ฒ ์ต๋๋ค.
ย
15.5.1 useClick Hook ์ด๋?
ย
ํน์ ์์์ ๋ํ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ๊ด๋ฆฌํ ๋ ์ฌ์ฉํ๋ ์ปค์คํ
ํ
์
๋๋ค.
useRef
๋ฅผ ์ฌ์ฉํ์ฌ ์ฃผ์ด์ง ํจ์์ ๋ํ ํด๋ฆญ์ ์ถ์ ํ๊ฑฐ๋ onClick
์ด๋ฒคํธ๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค. useClick
์ ์ฌ์ฉํ๋ฉด ํด๋ฆญ์ ์ฒ๋ฆฌํ๋ ๋ก์ง์ ๋ณ๋์ ํจ์๋ก ๋ถ๋ฆฌํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๋ณด๋ค ๊น๋ํ๊ณ ์ฒด๊ณ์ ์ผ๋ก ์ ์งํ ์ ์์ต๋๋ค.ย
๋ค์๋งํด ํด๋ฆญ ์ด๋ฒคํธ๋ก ์์ฃผ ์ฌ์ฉํ๋ ํจ์๊ฐ ์๋ค๋ฉด,
onClick
์์ฑ๊ฐ์ผ๋ก ์
๋ ฅํ๋ ๋์ ์ useRef
๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ํด๋น ์์๋ฅผ ํด๋ฆญํ์ ๋ ์ด๋ฒคํธ ํจ์๊ฐ ์คํ๋ ์ ์๋๋ก ๋ง๋ค์ด์ฃผ๋ ๊ฒ์
๋๋ค.ย
15.5.2 useClick์ ์ ์ฌ์ฉํ ๊น์?
ย
์ปดํฌ๋ํธ๋ง๋ค DOM ์์์ ํด๋ฆญ์ด๋ฒคํธ๋ฅผ ์ค์ผ ํ๋ค๋ฉด ๊ฐ ์ปดํฌ๋ํธ์
onClick
์ด๋ฒคํธ๋ฅผ ์
๋ ฅํด์ฃผ์ด์ผ ํ๋ ๋ฐ๋ณต ์์
์ด ์ด๋ฃจ์ด์ง๊ฒ ๋ ๊ฒ์
๋๋ค. ์ด๋ฌํ ๋นํจ์จ์ ์ธ ๋ฐ๋ณต ์์
๋ณด๋ค ref ์์ฑ๊ฐ์ ๋ถ์ฌํ์ฌ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํจ๋ค๋ฉด ์ฝ๋๋ฅผ ๋์ฑ ๊ฐ๊ฒฐํ๊ฒ ์ธ ์ ์๊ณ ์ ์ง๋ณด์ ๋ํ ํธ๋ฆฌํ๊ฒ ๋ ๊ฒ์
๋๋ค.ย
15.5.3 useClick ์ ์ฉํ๊ธฐ
ย
useClick
์ด ์ด๋ป๊ฒ ์ฐ์ด๋์ง, ์๋ ์ฌ์ฉ ์์ ๋ฅผ ํตํด ๊ฐ๋จํ๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค.ย
const useClick = (onClick) => { if(typeof onClick !== "function"){ return; } }
ย
useClick
์ปค์คํ
ํ
์ ์ ์ธํ๊ณ , ํ๋ผ๋ฏธํฐ๋ก onClick
์ด๋ผ๋ ์ด๋ฆ์ ๋ถ์์ต๋๋ค. onClick
์ ์กฐ๊ฑด์์ ๊ฑธ์ด์ ํจ์๊ฐ ์๋๋ผ๋ฉด returnํ์ฌ ํจ์์ ๋์์ ๋๋ด๋๋ก ํ๊ณ ๋ค๋ฅธ ์คํ๋ฌธ์ด ๋์ํ์ง ์๋๋ก ์์ฑํ์ต๋๋ค.ย
์๋ ์์ ์ฒ๋ผ
useRef
๋ฅผ ์ฌ์ฉํ์ฌ ์์(element)๋ฅผ ํด๋ฆญํ์ ๋ ์ด๋ฒคํธ ํจ์๊ฐ ๋์ํ ์ ์๋๋ก ๋ง๋ค์ด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.ย
useEffect(()=>{ if(element.current){ element.current.addEventListener("click", onClick); } return () => { if (element.current){ element.current.removeEventListener("click", onClick); } } }, [])
ย
useEffect
๋ฅผ ์ฌ์ฉํ ์ด์ ๋ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ์ํ์ผ ๋๋ง ์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํ๋๋ก ํ์ฌ ์ฌ๋ ๋๋ง์ด ๋ ๋๋ง๋ค ์๋กญ๊ฒ ์ด๋ฒคํธ๊ฐ ๋ฑ๋ก๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํจ์
๋๋ค.element.current
๊ฐ ์์ ๋์๋ง ์ด๋ฒคํธ ํจ์๊ฐ ์์ฑ๋์ด์ผ ํ๋ฉฐ, ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ํ์ง ์์ผ๋ฉด react์ ๋์์๋ฆฌ์ ๋ฐ๋ผ ์ด๋ฒคํธ๊ฐ ์ถ๊ฐ๋์ง ์๊ธฐ ๋๋ฌธ์ element.current
๊ฐ ์์๋์๋ง useEffect
๊ฐ ์คํ๋๋๋ก ์กฐ๊ฑด๋ฌธ์ ์ถ๊ฐํ์ต๋๋ค.์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ ์ํ์ผ ๋ ์ด๋ฒคํธ ํจ์๊ฐ ์ฌ๋ผ์ง๋๋ก clean-upํ๋
useEffect
๋ฌธ๋ฒ์ ์ฌ์ฉํ์์ต๋๋ค. ํ๋ก์ ํธ ๋ณผ๋ฅจ์ด ์ปค์ง๋ฉด ์ด๋ฒคํธ ์ถฉ๋์ด ๋ฐ์ํ ์ ์์ผ๋ฉฐ, ์ค๋๋ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์ด๋ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.ย
์๋๋ useClick ์ฌ์ฉ ์์ ์ฝ๋์
๋๋ค.
import { useEffect } from 'react'; import { useRef } from 'react'; const useClick = (onClick) => { if(typeof onClick !== "function"){ return; } const element = useRef(); useEffect(()=>{ if(element.current){ element.current.addEventListener("click", onClick); } return () => { if (element.current){ element.current.removeEventListener("click", onClick); } } }, []) return element; } export default useClick
ย
import React from 'react' import useClick from './useClick'; function App() { const repeatedFunction = () => console.log("say hello"); const title = useClick(repeatedFunction); return ( <div> <h1 ref={title}>Hi</h1> </div> ) } export default App
ย
์์ฑ๋
useClick
์ปค์คํ
ํ
์ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.์์ ์์ ์์
useClick
์ ์ธ์๋ก ๋ค์ด๊ฐ๋ repeatedFunction
์ ํด๋น ์ปดํฌ๋ํธ๋ฅผ ํด๋ฆญํ์ ๋ ๋ฐ๋ณต์ ์ผ๋ก ๋์๋๋ ํจ์์
๋๋ค.title
์ useClick(sayHello)
์ ๋ด๋ ๋ณ์์ด๋ฉฐ ref ์์ฑ ๊ฐ์ผ๋ก ์
๋ ฅ๋ฉ๋๋ค. ์
๋ ฅ๋ ์์๋ฅผ ํด๋ฆญํ์ ๋ repeatedFunction
์ด ํด๋ฆญ ์ด๋ฒคํธ ํจ์๋ก ๋์ํ๊ฒ ๋ฉ๋๋ค.ย
ย
ย
ย
์ง๊ธ๊น์ง ์์ฑํ ์ฝ๋๋ฅผ ๊ฐ์ง๊ณ
useClick
์ปค์คํ
ํ
์ด ์ ๋์ํ๋์ง ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ ์คํ์์ผ๋ณด์์ต๋๋ค.์ด์ฒ๋ผ ์ปดํฌ๋ํธ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ํด๋ฆญํ์ ๋ ๋์ผํ ํจ์๊ฐ ํด๋ฆญ์ด๋ฒคํธ๋ก ๋์๋์ด์ผ ํ๋ค๋ฉด
useClick
์ปค์คํ
ํ
์ ์ด์ฉํ์ฌ ref ์์ฑ ํ๋๋ง์ผ๋ก๋ ํธ๋ฆฌํ๊ฒ ์ด๋ฒคํธ ํจ์๋ฅผ ์คํ์ํค๋ ๋ชจ์ต์ ๋ณด์ค ์ ์์ต๋๋ค.ย
15.6 (์ค์ต3) useToggle
ย
15.6.1 useToggle Hook์ด๋?
ย
ํ ๊ธ์ด๋ ๋ ๊ฐ์ง ์ํ๋ง์ ๊ฐ์ง๊ณ ์์ด ์๋ก ๋ค๋ฅธ ๊ฐ์ผ๋ก ์ ํํ ์ ์๋ ๊ธฐ๋ฅ์
๋๋ค. ์ด๋ ๊ฒ ๋๋ฃจ ์ฌ์ฉ๋๋ ํ ๊ธ ๊ธฐ๋ฅ์ ์ผ์ผ์ด ๋์ผํ ๋ก์ง์ ๋ฐ๋ณตํ์ฌ ์ฐ๋ ๊ฒ๋ณด๋ค ์ปค์คํ
ํ
์ผ๋ก ๋ง๋ค์ด ์ฌ์ฉํ๋ค๋ฉด ์ ์ฉํ๊ฒ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. useToggle Hook์ ์ฒดํฌ๋ฐ์ค๋ ๋ฌผ๋ก ๋คํฌ ๋ชจ๋ ์ ํ์ด๋ ๋ชจ๋ฌ ์ฐฝ ์ด๊ธฐ ๋ฑ์ ์ ํ์ด ๊ฐ๋ฅํ ์์
์ ์ํํ๋ ค๋ ๊ฒฝ์ฐ์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ ํ
์
๋๋ค.
ย
ํ ๊ธ ๋ก์ง์ ์ฌ์ฌ์ฉ์ ์ํ useToggle ์ปค์คํ
ํ
์ ์๋์ ๊ฐ์ด ๊ตฌํํ ์ ์์ต๋๋ค.
ย
import { useState } from "react"; const useToggle = (initialValue = false) => { const [value, setValue] = useState(initialValue); const toggleValue = () => { setValue(!value) }; return [value, toggleValue]; }; export default useToggle;
ย
useToggle Hook์ ์ฌ์ฉํ๋ฉด ํ ๊ธ์ ๊ด๋ฆฌํ๋ ์ฝ๋๋ง๋ค ๋์ผํ ๋ก์ง์ ๋ฐ๋ณตํ ํ์ ์์ด useToggle Hook์ ๊ฐ์ ธ์์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. useToggle Hook์ ๋งค๊ฐ๋ณ์๋ก true ๋๋ false์ธ boolean ๊ฐ์ ์ ๋ฌํ์ฌ ์ํ๋ฅผ ๋ฐ๋ ๊ฐ์ผ๋ก ์ ํ ์ํต๋๋ค. ๋งค๊ฐ๋ณ์๋ก๋ ์ด๊น๊ฐ์ ๋ฐ์ผ๋ฉฐ, ๊ฐ์ด ์์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ๊ฐ์ผ๋ก false๊ฐ ์ง์ ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ฌ ํ ๊ธ์ ์ํ๋ฅผ ๋ํ๋ด๋ state ๋ณ์์ ํ ๊ธ์ ์ํ๋ฅผ ์ ํ์ํค๋ ํจ์๋ฅผ ์ค์ ํ์ฌ ์ด๋ฅผ ๋ฐฐ์ด๋ก ๋ฐํํฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ useToggle Hook์ ์ฌ์ฉํ๋ฉด ํ ๊ธ์ ์ค์ ํ๋ ค๋ ์ํ๊ฐ์ ๊ธฐ์ตํ๊ณ ์ด๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค.
ย
15.6.2 useToggle ์ ์ฉํ๊ธฐ
ย
useToggle ํ
์ ์ฌ์ฉํ์ฌ ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญ ํจ์ ๋ฐ๋ผ ํ
์คํธ๊ฐ ๋ณ๊ฒฝ๋๋ ์ฒซ ๋ฒ์งธ ์์ ์ ๋ฒํผ์ ํด๋ฆญ ํจ์ ๋ฐ๋ผ ๋ฆฌ์คํธ๋ฅผ ํ์ธํ๊ณ ์จ๊ธธ ์ ์๋ ๋ ๋ฒ์งธ ์์ ๋ฅผ ํตํด useToggle ํ
์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
ย
๋จผ์ useToggle ํ
์ import ํด์ ์ฌ์ฉํ ์ ์๋๋ก useToggle.js ํ์ผ์ ํ๋ ์๋ก ์์ฑํฉ๋๋ค.
ย
import { useState } from "react"; const useToggle = (initialValue = false) => { const [value, setValue] = useState(initialValue); }
ย
useToggle ํจ์๋ boolean ๊ฐ์ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ฉํ์ฌ ์ด๊น๊ฐ์ ์ ๋ฌํฉ๋๋ค. ํ ๊ธ์ ์ํ๋ฅผ ๋ํ๋ด๋ value๋ผ๋ state ๋ณ์์ ์ด state ๋ณ์๋ฅผ ๊ด๋ฆฌํ๋ ํจ์ setValue๋ฅผ ๋ฐฐ์ด์ ๋ด์ ์ ์ธํด ์ฃผ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ useState Hook์ ์ธ์๋ก ์ด๊น๊ฐ์ ์ ๋ฌํด ์ฃผ๊ณ , useState๋ฅผ Import ํด์ค๋๋ค.
ย
์ด์ ํ ๊ธ์ ์ํ๋ฅผ ๋ํ๋ด๋ value์ ํ ๊ธ์ ์ํ๋ฅผ ์ ํ์ํค๋ ํจ์ setValue๋ฅผ ํตํด ํ ๊ธ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
import { useState } from "react"; const useToggle = (initialValue = false) => { const [value, setValue] = useState(initialValue); const toggleValue = () => { setValue(!value) }; return [value, toggleValue]; };
ย
๋ค์์ผ๋ก๋ useToggle์ ํธ๋ค๋งํ๋ toggleValue๋ผ๋ ํจ์๋ฅผ ๋ง๋ค์ด์ฃผ๊ฒ ์ต๋๋ค. toggleValue ํจ์์๋ ์ฝ๋ฐฑ ํจ์๋ก ํ ๊ธ์ ์ํ๋ฅผ ์ ํ์ํค๋ ํจ์ setValue ์์ ํ ๊ธ์ ์ํ๋ฅผ ๋ํ๋ด๋ state ๋ณ์ value๋ฅผ ๋ด์ ๊ฐ์ ๊ฐฑ์ ํฉ๋๋ค. ์ด๋ฅผ ํตํด toggleValue ํจ์๋ ํ ๊ธ์ ์ํ๋ฅผ ๋ฐ๋ ๊ฐ์ผ๋ก ์ ํ์ํค๋ ์ค์์น ์ญํ ์ ํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ state ๋ณ์ value์ toggleValue ํจ์๋ฅผ ๋ฐฐ์ด์ ๋ด์ ๋ฐํํฉ๋๋ค.
ย
import { useState } from "react"; const useToggle = (initialValue = false) => { const [value, setValue] = useState(initialValue); const toggleValue = () => { setValue(!value) }; return [value, toggleValue]; }; export default useToggle;
ย
๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก useToggle์ export ํด์ฃผ๋ฉด App.js ํ์ผ์์ useToggle ํ
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ย
useToggle ์ปค์คํ
ํ
์ ์์ฑ์์ผฐ์ผ๋ ์ด์ App.js ํ์ผ์์ ์ ์ฉํด ๋ณด๊ฒ ์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญ ํจ์ ๋ฐ๋ผ ํ
์คํธ๊ฐ ๋ณ๊ฒฝ๋๋ ์ฝ๋์ ๋ฒํผ์ ํด๋ฆญ ํจ์ ๋ฐ๋ผ ๋ฆฌ์คํธ๋ฅผ ํ์ธํ๊ณ ์จ๊ธธ ์ ์๋ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํ๋ฏ๋ก, App ํจ์ ์์ ์๋ก ๋ค๋ฅธ ์ํ ๊ฐ์ด ๋ด๊ธด useToggle Hook์ ๋ ๋ฒ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
ย
import useToggle from "./useToggle"; function App() { const [isChecked, setIsChecked] = useToggle(); const [isListOpen, setListOpen] = useToggle(); return; } export default App;
ย
์์ ๊ฐ์ด ์ฒดํฌ๋ฐ์ค์ ์ฌ์ฉ๋ isChecked ๋ณ์์ ๋ฆฌ์คํธ๋ฅผ ํ์ธํ๋ ๋ฒํผ์ ์ฌ์ฉ๋ isListOpen์ด๋ผ๋ state ๋ณ์๋ฅผ ๊ฐ๊ฐ ์ ์ธํด ์ฃผ์์ต๋๋ค. useToggle์ ์ด๊น๊ฐ์ ๊ฐ์ด ๋น์ด์์ ๊ฒฝ์ฐ false๊ฐ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ง์ ๋ฉ๋๋ค.
ย
15.6.3 (์์ 1) useToggle Hook์ ํ์ฉํ์ฌ ์ฒดํฌ๋ฐ์ค ๋ง๋ค๊ธฐ
function App() { const [isChecked, setIsChecked] = useToggle(); return ( <> <h3>์๋ฃ๋ฅผ ์ฃผ๋ฌธํ์๊ฒ ์ด์? ๐ฅค</h3> <label for='check'> <input type='checkbox' id='check' onChange={setIsChecked} /> {isChecked ? "๋ค" : "์๋์"} </label> </> ); }
ย
๋จผ์ ์ฌ์ฉ์์๊ฒ ์ ๋ณด๋ฅผ ์
๋ ฅ๋ฐ์ ์ ์๋๋ก input ํ๊ทธ๋ฅผ ์์ฑํ๊ณ ์ฒดํฌ ๋ฐ์ค๋ฅผ ์์ฑํ๊ธฐ ์ํด type ์์ฑ์ โcheckboxโ๋ก ์ง์ ํด ์ฃผ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญ ํจ์ ๋ฐ๋ผ ํ
์คํธ๋ฅผ ๋ณ๊ฒฝ์์ผ์ฃผ๊ธฐ ์ํด onChange ์ด๋ฒคํธ์ setIsChecked ํจ์๋ฅผ ์ถ๊ฐํด ์ฃผ์๊ณ , ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญํ ๋๋ง๋ค isChecked์ ๊ฐ์ด ๋ฐ๋์ด ํ
์คํธ๊ฐ ๋ณ๊ฒฝ๋ ๊ฒ์
๋๋ค.
ย
ย
์คํ ํ๋ฉด์ ํ์ธํด๋ณด๋ฉด ์์ ๊ฐ์ด ์ฒดํฌ๋ฐ์ค๋ฅผ ์ ํํ๊ธฐ ์ ๊น์ง๋ โ์๋์โ๋ผ๋ ํ
์คํธ๊ฐ ํ์ธ๋ฉ๋๋ค.
ย
ย
์ฒดํฌ๋ฐ์ค๋ฅผ ์ ํํ๋ฉด ์์ ๊ฐ์ด โ๋คโ๋ผ๋ ํ
์คํธ๋ก ๋ณ๊ฒฝ๋๋ฉฐ, ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญํ ๋๋ง๋ค ํ
์คํธ๊ฐ ๋ฐ๋ณต์ ์ผ๋ก ๋ณ๊ฒฝ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ useToggle Hook์ ์ฌ์ฉํ์ฌ ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญ ํจ์ ๋ฐ๋ผ ํ
์คํธ๊ฐ ๋ณ๊ฒฝ๋๋ ์ฒซ ๋ฒ์งธ ์์ ๋ฅผ ํ์ธํด ๋ณด์์ต๋๋ค.
ย
์ด๋ฒ์๋ useToggle Hook์ ์ฌ์ฉํ์ฌ ๋ฒํผ์ ํด๋ฆญํ ๋๋ง๋ค ๋ฆฌ์คํธ๋ฅผ ํ์ธํ๊ณ ์จ๊ธธ ์ ์๋ ์์ ๋ฅผ ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
ย
15.6.4 (์์ 2) useToggle Hook์ ํ์ฉํ์ฌ ๋ฆฌ์คํธ ์ถ๋ ฅํ๊ธฐ
function App() { const [isListOpen, setListOpen] = useToggle(); return ( <div> <h3>์ค๋์ ์ถ์ฒ ์๋ฃ๋ฅผ ํ์ธํด์ฃผ์ธ์ ๐ฅค</h3> <button onClick={setListOpen}>์ค๋์ ์ถ์ฒ ์๋ฃ ํ์ธํ๊ธฐ</button> {isListOpen && ( <ul> <li>๋ฌ์ฝคํ ๋ผ์ด์บฃํ๋ผํธ์น๋ ธ</li> <li>๋ง์๋ ๊ฐ๋ฆฌ์์ดํฌ</li> <li>์คํํด๋ง ์จ์ด๋์์ด๋</li> <li>์ํผํ ๋นํค์ฃผ์ค</li> </ul> )} </div> ); }
ย
๋ฒํผ ํ๊ทธ์ onClick ์ด๋ฒคํธ๋ฅผ ์ฃผ์ด setListOpen ํจ์๋ฅผ ์ถ๊ฐํด ์ฃผ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ค๊ดํธ ์์ ๋
ผ๋ฆฌ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ state ๋ณ์ isListOpen๊ณผ ul ํ๊ทธ ์์ ๊ฐ์ธ์ธ li ํ๊ทธ๋ค์ ํจ๊ป ์์ฑํด์ ์กฐ๊ฑด๋ถ๋ก ๋ ๋๋ง ๋ ์ ์๋๋ก ํ์์ต๋๋ค. ์ด์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํฌํจ๋ ๋ฒํผ์ด ํด๋ฆญ๋ ๋๋ง๋ค ํ ๊ธ์ ์ํ๊ฐ ์ ํ๋์ด ๋ฆฌ์คํธ๊ฐ ๋ณด์ด๊ธฐ๋, ์จ๊ฒจ์ง๊ธฐ๋ ํ ๊ฒ์
๋๋ค. ์คํ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
ย
ย
๋ฒํผ์ ํด๋ฆญํ๊ธฐ ์ ์๋ ์์ ๊ฐ์ด ๋ฆฌ์คํธ๊ฐ ํ์ธ๋์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์๋์ ๊ฐ์ด ์๋ฃ ๋ฆฌ์คํธ๊ฐ ๋ณด์ด๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํฌํจ๋ ๋ฒํผ์ด ํด๋ฆญ๋ ๋๋ง๋ค ๋ฐ๋ณต์ ์ผ๋ก ํ ๊ธ์ ์ํ๊ฐ ์ค์์น ์ญํ ์ ํ๋ฉฐ ๋ฐ๋ ๊ฐ์ผ๋ก ์ ํ๋ฉ๋๋ค.
ย
ย
์ง๊ธ๊น์ง useToggle Hook์ ์ฌ์ฉํ์ฌ ๋ฒํผ์ ํด๋ฆญ ํจ์ ๋ฐ๋ผ ๋ฆฌ์คํธ๊ฐ ๋ณด์ด๊ณ ์จ๊ฒจ์ง๋ ๋ ๋ฒ์งธ ์์ ๊น์ง ํ์ธํด ๋ณด์์ต๋๋ค. ์ด์ฒ๋ผ ์๋ก ๋ค๋ฅธ ๋ฐ๋ ๊ฐ์ผ๋ก ์ ํํ๋ ์์
์ ์ํํ๋ ค๋ ๊ฒฝ์ฐ, useToggle ์ปค์คํ
ํ
์ ๋ง๋ค์ด ์ฌ์ฌ์ฉ ํ๋ค๋ฉด ํ ๊ธ์ ๊ด๋ฆฌํ๋ ์ฝ๋๋ง๋ค ๋์ผํ ๋ก์ง์ ๋ฐ๋ณตํ ํ์ ์์ด ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
ย
์์์ ์์ฑํ๋ ๋ ์์ ์ฝ๋๋ฅผ App ํจ์์ ๊ฐ์ด ์์ฑํด ๋ณด๋ฉด ์๋์ ๊ฐ์ ์คํ ํ๋ฉด์ ํ์ธํ ์ ์์ผ๋ฉฐ ์ต์ข
์ฝ๋๋ ํ๋จ์์ ํ์ธํ ์ ์์ต๋๋ค.
ย
ย
์ต์ข
์ฝ๋
import useToggle from "./useToggle"; function App() { const [isChecked, setIsChecked] = useToggle(); const [isListOpen, setListOpen] = useToggle(); return ( <> <h3>์๋ฃ๋ฅผ ์ฃผ๋ฌธํ์๊ฒ ์ด์? ๐ฅค</h3> <label for='check'> <input type='checkbox' id='check' onChange={setIsChecked} /> {isChecked ? "๋ค" : "์๋์"} </label> <div> <h3>์ค๋์ ์ถ์ฒ ์๋ฃ๋ฅผ ํ์ธํด์ฃผ์ธ์ ๐ฅค</h3> <button onClick={setListOpen}>์ค๋์ ์ถ์ฒ ์๋ฃ ํ์ธํ๊ธฐ</button> {listOpen && ( <ul> <li>๋ฌ์ฝคํ ๋ผ์ด์บฃํ๋ผํธ์น๋ ธ</li> <li>๋ง์๋ ๊ฐ๋ฆฌ์์ดํฌ</li> <li>์คํํด๋ง ์จ์ด๋์์ด๋</li> <li>์ํผํ ๋นํค์ฃผ์ค</li> </ul> )} </div> </> ); } export default App;
import { useState } from "react"; const useToggle = (initialValue = false) => { const [value, setValue] = useState(initialValue); const toggleValue = () => { setValue(!value) }; return [value, toggleValue]; }; export default useToggle;
ย
15.7 (์ค์ต4) useAxios
ย
15.7.1 axios๋?
ย
๋จผ์ axios๋, ํด๋ผ์ด์ธํธ๊ฐ ์น์๋ฒ์ ์ฌ์ฉ์ ์์ฒญ์ ๋ชฉ์ /์ข
๋ฅ๋ฅผ ์๋ฆฌ๋ ์๋จ์ธ HTTP ๋ฉ์๋์ ์ด์ฉํด ๋ฐ์ดํฐ ํต์ ์ ํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
HTTP ๋ฉ์๋์๋ get,post,put,delete์ ๊ฐ์ด ๋ง์ด ์ฌ์ฉํ๋ ๋ฉ์๋๊ฐ ์์ต๋๋ค.
get
: ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๋ ์ฌ์ฉํฉ๋๋ค.
post
: ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ๋ ์ฌ์ฉํฉ๋๋ค.
put
: ๊ธฐ์กด์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
delete
: ๊ธฐ์กด์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
ย
์๋ฅผ ๋ค์ด, ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ๋๋ axios ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํฉ๋๋ค.
์ฒซ ๋ฒ์งธ ์ธ์๋ url, ๊ทธ๋ฆฌ๊ณ ๋ ๋ฒ์งธ ์ธ์๋ headers์ ์ถ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๊ฐ์ฒด ํ์์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํฉ๋๋ค.
ย
https://jsonplaceholder.typicode.com/ ๋ ๋ฐฑ์๋ ์๋ฒ๊ฐ ์์ ๋ ์์๋ก ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด api๋ฅผ ํ
์คํธํด ๋ณผ ์ ์๋ ์ฌ์ดํธ์
๋๋ค. POST, PUT, PATCH, DELETE ์์ฒญ์ ์ค์ ๋ก ์ด๋ฃจ์ด์ง์ง๋ ์์ง๋ง ๋ง์น ๊ฐ์ง์ธ ๊ฒ์ฒ๋ผ ํ์๊ฐ๋๋ฉฐ, GET ์์ฒญ์ ๊ฒฝ์ฐ https://jsonplaceholder.typicode.com/ ์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
ย
axios.post(`https://jsonplaceholder.typicode.com/posts`, { headers: { accept: '*/*' }, data: { userId: 1, id: 19392, title: 'title', body: 'Sample text', }, })
๋ง์ฝ, ๋ค์๊ณผ ๊ฐ์ด axios์ ๋ฉ์๋๋ฅผ ์ ์ง ์๋๋ค๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก get ๋ฉ์๋๊ฐ ์คํ๋๊ณ
๋ ๋ฒ์งธ ์ธ์์ ํ๋กํผํฐ๋ก method๋ฅผ ์์ฑํ๋ฉด ์์ ๊ฐ์ ๊ฒฐ๊ด๊ฐ์ ์ป์ ์ ์์ต๋๋ค.
ย
axios(`https://jsonplaceholder.typicode.com/posts`, { method: 'POST', headers: { accept: '*/*' }, data: { userId: 1, id: 19392, title: 'title', body: 'Sample text', }, })
๊ทธ๋ ๋ค๋ฉด ๋ค์ ์์ ๋ฅผ ํตํด ์ค์ ๋ก axios๋ฅผ ํ์ฉํด ์์ฒญ์ ํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
ย
15.7.2 axios ์์ฒญ
ย
import axios from "axios"; import { useEffect, useState } from "react"; function App() { const [response, setResponse] = useState(null); const [error, setError] = useState(""); const [loading, setLoading] = useState(true); const fetchData = async () => { try { const res = await axios({ method: "get", url: "https://jsonplaceholder.typicode.com/posts", }); console.log(res); setResponse(res.data); } catch (error) { setError(error); } finally { setLoading(false); } }; useEffect(() => { fetchData(); }, []); return ( <div className="app"> {loading ? ( <div>Loading...</div> ) : ( <> <h3>๊ฒ์๊ธ ๋ชฉ๋ก</h3> <ul> {response && response.map((res, index) => ( <li key={index}> <h4> ์ ๋ชฉ :{error && error.message} {res && res.title} </h4> <p>{res.body}</p> </li> ))} </ul> </> )} </div> ); } export default App;
์์ ์์ ๋ฅผ ๋ณด๋ฉด fetchData๋ฅผ ํตํด url๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ์์ต๋๋ค. ๊ทธ ๋ค ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์๋์ ๊ฐ์ด ํ๋ฉด์ ๋ ๋๋งํด์ฃผ๊ณ ์์ต๋๋ค.
ย
ย
์์ ์ ๊ฐ์ด ๋จ ํ ๋ฒ axios ์์ฒญ์ด ์๋ค๋ฉด ์๊ด์ด ์๊ฒ ์ง๋ง ๋น์ทํ ์์ฒญ์ด ์ฌ๋ฌ ๊ฐ์ ์ปดํฌ๋ํธ์์ ์คํ๋๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?? ๊ฐ์ ์ฝ๋๊ฐ ์ปดํฌ๋ํธ๋ง๋ค ์์ฑ๋ ๊ฒ์ด๊ณ ์ด๋ ๋งค์ฐ ๋นํจ์จ์ ์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค. ์ด์ฒ๋ผ API๋ฅผ ํธ์ถํ๋ ์ฝ๋๊ฐ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณต๋๋ ๊ฒ์ ๋ง์์ฃผ๊ณ ์ฌ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋๋ ์ปค์คํ
ํ
์ด useAxios์
๋๋ค. ์ด์ด์ง๋ ์์ ์์ ๊ธฐ์กด์ ์์ฑํ์๋ ์ฝ๋๋ฅผ ์ปค์คํ
ํ
์ผ๋ก ๋ง๋ค์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
ย
15.7.3 useAxios ์ ์ฉํ๊ธฐ
ย
- useAxios ์ปดํฌ๋ํธ
import { useState, useEffect } from 'react'; import axios from 'axios'; axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com'; function useAxios(params) { const [response, setResponse] = useState(null); const [error, setError] = useState(''); const [loading, setLoading] = useState(true); const fetchData = async (params) => { try{ const res = await axios(params); setResponse(res.data); }catch(err) { setError(err); } finally{ setLoading(false); }; }; useEffect(() => { fetchData(params); }, []); return { response, error, loading }; }; export default useAxios;
์์ useAxios ์ปดํฌ๋ํธ๋ ๋ ๋๋ง์ด ๋ ๋ ์ต์ด๋ก ํ ๋ฒ fetchDataํจ์๋ฅผ ์คํํ๋ฉฐ response, error, loading์ return ํ๊ณ params๋ผ๋ ์ธ์๋ฅผ ๋ฐ์ต๋๋ค. response๋ ์์ฒญ๋ฐฉ์์ ๋ฐ๋ฅธ ๋ฐ์ดํฐ๊ฐ ๋๊ณ , error๋ ์์ฒญ์ ์ฑ๊ณตํ์ง ๋ชปํ์์ ๋ ์๋ฌ ๋ฉ์์ง๊ฐ ๋ฉ๋๋ค. ๋ํ loading์ ์์ฒญ์ด ์๋ฃ๋๊ธฐ ์ ๊น์ง ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง ๋ฉ์์ง๋ฅผ ์ปจํธ๋กคํ๋ ์ญํ ์ ํฉ๋๋ค.
ย
- useAxios๋ฅผ ํ์ฉํ์ฌ ๋ฐ๊พธ์ด์ค ์์
import useAxios from './useAxios'; function App() { const { response, error, loading } = useAxios({ method: 'GET', url: '/posts', }); // {url, method, body, headers}๋ก ๊ตฌ์ฑ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ useAxios ์ ์ธ์๋ฅผ ์ ๋ฌํ์ฌ HTTP ํธ์ถ์ ์ํํฉ๋๋ค. return ( <div className="app"> {loading ? ( <div>Loading...</div> ) : ( <> <h1>๊ฒ์๊ธ ๋ชฉ๋ก</h1> <ul> {response && response.map( (res, index) => <li key={index}> <h1> ์ ๋ชฉ : {error && error.message} {res && res.title} </h1> <p>{res.body}</p> </li> )} </ul> </> )} </div> ); }; export default App;
์์ ๊ฐ์ด ๊ธฐ์กด์๋ ํ ์ปดํฌ๋ํธ์์ ์กด์ฌํ๋ axios ์์ฒญ์ useAxios๋ก ๋ง๋ค์ด ์ฌ์ฉํด์ฃผ์์ต๋๋ค. ํ๋์ ๋ณด์๋ ์ฝ๋๊ฐ ๋งค์ฐ ๊น๋ํด์ง ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ์์ ์์ ๋ณด์ด๋ฏ ์ปค์คํ
ํ
์ ํตํด ๊ฐ์ ์ฝ๋๋ฅผ ์ค์ผ ์ ์์ผ๋ฉฐ ์ด๋ ๊ณง ์ ์ง๋ณด์์๋ ๊ต์ฅํ ์ฉ์ดํด์ง๋๋ค. ์ด์๊ฐ์ด ์ปค์คํ
ํ
์ ํ์ฉํ๋ฉด ๋ฐ๋ณต๋๋ ์ฝ๋๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.