๐Ÿ“Ž

15. Custom Hook

15.1 ์ปค์Šคํ…€ ํ›…(Custom Hook)์ด๋ž€?

์ปค์Šคํ…€ ํ›…์€ ๋ฆฌ์•กํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ๋‚ด ํŠน์ • ๋กœ์ง์„ ๋ถ„๋ฆฌํ•œ ํ•จ์ˆ˜๋กœ, ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ปค์Šคํ…€ ํ›…์€ ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ํŠน์ • ๋กœ์ง์„ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•ด ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ๋ฐ˜๋ณต์„ ์ค„์ด๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ๋งฅ๋ฝ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
ย 
์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ์—ฌ๋Ÿฌ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํŠน์ • ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ์—์„œ ํŠน์ • ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”์— ๋”ฐ๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋„์ž…ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ์— ์ ํ•ฉํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์ปค์Šคํ…€ ํ›…์„ ์ง์ ‘ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
์ปค์Šคํ…€ ํ›…์˜ ์žฅ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  1. ์žฌ์‚ฌ์šฉ์„ฑ
    1. ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ค‘๋ณต๋˜๋Š” ๋กœ์ง์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๋กœ์ง์˜ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.
      ย 
  1. ๊ฐ€๋…์„ฑ
    1. ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปค์Šคํ…€ ํ›…์˜ ๋‚ด๋ถ€ ๋กœ์ง์„ ์ •ํ™•ํžˆ ๋ชฐ๋ผ๋„ ์–ด๋–ค ๊ฐ’์ด ๋“ค์–ด๊ฐ€์„œ ์–ด๋–ค ๊ฒฐ๊ณผ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜๋Š”์ง€๊ฐ€ ๋ช…ํ™•ํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
      ย 
      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;
      useFetch ์ปค์Šคํ…€ ํ›…์„ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ
ย 
์ง€๊ธˆ๊นŒ์ง€ ์ฑ…์—์„œ ์†Œ๊ฐœ๋œ ๋ฆฌ์•กํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ํ›…๊ณผ ์ถ”๊ฐ€์ ์ธ ํ›…๋“ค์„ ํ™œ์šฉํ•ด ์—ฌ๋Ÿฌ๋ถ„์ด ์›ํ•˜๋Š” ์ปค์Šคํ…€ ํ›…์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์ฑ•ํ„ฐ์—์„œ๋Š” ์ปค์Šคํ…€ ํ›… ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ ๊ณผ ์‚ฌ์šฉ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๊ณ , ๋ฆฌ์•กํŠธ์— ๋‚ด์žฅ๋œ ํ›…๋“ค์„ ํ™œ์šฉํ•œ ๋‹ค์–‘ํ•œ ์ปค์Šคํ…€ ํ›… ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
ย 

15.2 ์ปค์Šคํ…€ ํ›… ์ฃผ์˜์‚ฌํ•ญ

15.2.1 ์ฃผ์˜์‚ฌํ•ญ

ย 
์ปค์Šคํ…€ ํ›…๋„ Hook์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฑ…์˜ ์ดˆ๋ฐ˜๋ถ€์— ๋‹ค๋ฃจ์—ˆ๋˜ Hook์˜ ๊ทœ์น™์— ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.
  1. ์ตœ์ƒ์œ„(at the Top Level)์—์„œ๋งŒ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  1. ์˜ค์ง React ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  1. Hook์€ use๋กœ ์‹œ์ž‘ํ•ด์•ผํ•˜๋Š” ๊ทœ์น™์ด ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

15.2.2 ๊ณ ๋ ค์‚ฌํ•ญ

ย 
  1. ์ปค์Šคํ…€ ํ›…์ด ๊ผญ ํ•„์š”ํ•œ์ง€ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค.
๐Ÿ’ก
์žฌ์‚ฌ์šฉ๋  ๋ถ€๋ถ„์ด ๋งŽ์ง€ ์•Š์€๋ฐ ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•œ๋‹ค๋ฉด ์ฝ”๋“œ๋ฅผ ํ•œ๋ˆˆ์— ์ดํ•ดํ•˜๊ธฐ ํž˜๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ผญ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋ฉด ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
ย 
  1. ์ปค์Šคํ…€ ํ›…์˜ ์ด๋ฆ„์ด ์ง๊ด€์ ์ธ์ง€ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค.
๐Ÿ’ก
Hook์€ ์„ ์–ธ์ ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„ ์–ธ์ ์ด๋ผ๋Š” ๊ฒƒ์€ ์–ด๋–ค ๋ฐฉ๋ฒ•(HOW)์œผ๋กœ ํ•ด๊ฒฐํ• ์ง€๋ณด๋‹ค๋Š” ๋ฌด์—‡(WHAT)์„ ํ•ด์•ผ ํ• ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ useToggle์€ ๋ฌด์—‡์— ์“ฐ์ผ์ง€ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ โ€œ์–ด๋–ป๊ฒŒโ€๋ผ๋Š” ๋ฐฉ๋ฒ•๋ณด๋‹ค๋Š” โ€œ๋ฌด์—‡โ€์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ Hook์ธ์ง€ ์•Œ ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.
ย 
  1. ๋งŒ๋“ค์–ด์ง„ ์ปค์Šคํ…€ ํ›…์ด ์ˆœ์ˆ˜ํ•œ์ง€ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค.
๐Ÿ’ก
์šฐ๋ฆฌ๊ฐ€ ์„ ์–ธ์ ์œผ๋กœ ๋งŒ๋“  ์ปค์Šคํ…€ ํ›…์ด ์˜ˆ์ƒํ•œ ๋Œ€๋กœ ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•ด์„  ์ˆœ์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ˆœ์ˆ˜ํ•˜๋‹ค๋Š” ๊ฒƒ์€, ๊ฐ™์€ ์ธ์ž๋ฅผ ๋„ฃ์—ˆ์„ ๋•Œ ๊ฐ™์€ ๋™์ž‘์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ 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;
useFetch.js
ย 
์œ„ ์ฝ”๋“œ๋Š” ๋งค๋ฒˆ fetch๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์ƒˆ๋กœ์šด ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฒฝ์šฐ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด useFetch๋ผ๋Š” ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค์–ด ์ฝ”๋“œ ๋กœ์ง์˜ ํšจ์œจ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„ ์ฝ”๋“œ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋‹ค์‹œํ”ผ ์‚ฌ์šฉ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
ย 
์‚ฌ์šฉ๋ฐฉ๋ฒ•
  1. ์ปค์Šคํ…€ ํ›…์˜ ์ด๋ฆ„์€ use ๋กœ ์‹œ์ž‘๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    1. use ๋กœ ์‹œ์ž‘๋˜์ง€ ์•Š์œผ๋ฉด ํŠน์ •ํ•œ ํ•จ์ˆ˜๊ฐ€ ๊ทธ ์•ˆ์—์„œ Hook์„ ํ˜ธ์ถœํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
      ๐Ÿ’ก
      ๋ฆฌ์•กํŠธ ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์—์„œ ๊ฐ•์กฐํ•˜๋Š” ๊ด€์Šต์œผ๋กœ์จ ์ด๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์œผ๋ฉด ํŠน์ •ํ•œ ํ•จ์ˆ˜๊ฐ€ ๊ทธ ์•ˆ์—์„œ Hook์„ ํ˜ธ์ถœํ•˜๋Š”์ง€๋ฅผ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— Hook ๊ทœ์น™์˜ ์œ„๋ฐ˜ ์—ฌ๋ถ€๋ฅผ ์ž๋™์œผ๋กœ ์ฒดํฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
      ย 
  1. ์ปค์Šคํ…€ ํ›… ๋˜ํ•œ useState์™€ useEffect๊ณผ ๊ฐ™์€ ๋‚ด์žฅ ํ›…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    1. ์šฐ๋ฆฌ๋Š” useFetch ์„ ์ง์ ‘ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์•กํŠธ ๊ด€์ ์—์„œ ์ปดํฌ๋„ŒํŠธ๋Š” useState์™€ useEffect๋งŒ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋…๋ฆฝ์ ์ธ useState์™€ useEffect๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      ย 
  1. ๊ฐ™์€ ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋Š” state๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    1. ์ปค์Šคํ…€ ํ›…์€ ์ƒํƒœ ๊ด€๋ จ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋งค์ปค๋‹ˆ์ฆ˜์ด์ง€๋งŒ ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ๊ทธ ์•ˆ์˜ 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;
App.js
ย 
๊ทธ๋ฆผ 15-1๊ทธ๋ฆผ 15-1
๊ทธ๋ฆผ 15-1
ย 
์œ„ ์ฝ”๋“œ๋Š” 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]; // --- โ“ถ };
useInput.js
ย 
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;
App.js
ย 
๊ทธ๋ฆผ 15-2๊ทธ๋ฆผ 15-2
๊ทธ๋ฆผ 15-2
ย 
๋งŒ๋“ค์–ด๋†“์€ 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;
App.js
ย 
๊ทธ๋ฆผ 15-3๊ทธ๋ฆผ 15-3
๊ทธ๋ฆผ 15-3
ย 
์œ„ ์˜ˆ์ œ์—์„œ ๋งŒ๋“  input ์•„๋ž˜์— ์ดˆ๊นƒ๊ฐ’์„ ์ง€์ •ํ•˜์ง€ ์•Š์€ input์„ ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. โ“ต์—์„œ๋Š” ์œ„์—์„œ ๋งŒ๋“  input์ด ๋ฐ›๋Š” ๋ณ€์ˆ˜์™€ ๋‹ค๋ฅธ ๋ณ€์ˆ˜๋ช…์œผ๋กœ ์ง€์ •ํ•˜์—ฌ useInput์˜ ๋ฐ˜ํ™˜๊ฐ’์„ ๋ฐ›์•„์™”์Šต๋‹ˆ๋‹ค. ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋‘ ๊ฐœ์˜ input์ด ๊ฐ๊ฐ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ ๋˜๋Š” ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ useInput์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋ชจ๋“  input์€ ๋…๋ฆฝ์ ์ธ state๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜๋ฉฐ, ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
ย 
์ปค์Šคํ…€ ํ›… ์‚ฌ์šฉ ์ „ํ›„๋ฅผ ์‚ดํŽด๋ด„์œผ๋กœ์จ ์šฐ๋ฆฌ๋Š” ์ปค์Šคํ…€ ํ›…์„ ํ†ตํ•ด ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋ฉฐ, ํ•„์š”ํ•œ ๋ถ€๋ถ„์— ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋‹ค์–‘ํ•œ ์ปค์Šคํ…€ ํ›…์„ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
ย 

15.4 (์‹ค์Šต1) useTitle

ย 

15.4.1 Document Title

ย 
Document Title
์›น ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์˜ ์ƒ๋‹จ ํƒญ์—์„œ ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ์ œ๋ชฉ์„ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ•ด๋‹น ํŽ˜์ด์ง€์˜ ์ œ๋ชฉ์„ Document Title์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. Document Title์€ ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ์›น ํŽ˜์ด์ง€์˜ ํƒ€์ดํ‹€๋กœ, ๊ฐ ํŽ˜์ด์ง€์˜ ์ฃผ์ œ๋ฅผ ๊ฐ€์žฅ ์ž˜ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” ์š”์†Œ์ด์ž ํ•ด๋‹น ์›น ํŽ˜์ด์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์œ ์ €์—๊ฒŒ ํ˜„์žฌ ์ž์‹ ์ด ๋ณด๊ณ  ์žˆ๋Š” ์›น ํŽ˜์ด์ง€๊ฐ€ ์–ด๋–ค ํŽ˜์ด์ง€์ธ์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ์ค‘์š”ํ•œ ์š”์†Œ์ž…๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 15.4๊ทธ๋ฆผ 15.4
๊ทธ๋ฆผ 15.4
ย 
ํ•˜์ง€๋งŒ 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.js
ย 
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;
Login.js
ย 
๊ทธ๋ฆผ 15-5๊ทธ๋ฆผ 15-5
๊ทธ๋ฆผ 15-5
ย 
๊ทธ๋ฆฌ๊ณ  ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ 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
useClick.js
ย 
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
App.js
ย 
์™„์„ฑ๋œ useClick ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์œ„์˜ ์˜ˆ์ œ์—์„œ useClick์˜ ์ธ์ž๋กœ ๋“ค์–ด๊ฐ€๋Š” repeatedFunction์€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋™์ž‘๋˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
title์€ useClick(sayHello)์„ ๋‹ด๋Š” ๋ณ€์ˆ˜์ด๋ฉฐ ref ์†์„ฑ ๊ฐ’์œผ๋กœ ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ๋œ ์š”์†Œ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ repeatedFunction์ด ํด๋ฆญ ์ด๋ฒคํŠธ ํ•จ์ˆ˜๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
ย 
ย 
๊ทธ๋ฆผ 15-6๊ทธ๋ฆผ 15-6
๊ทธ๋ฆผ 15-6
ย 
ย 
์ง€๊ธˆ๊นŒ์ง€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  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.js
ย 
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.js
ย 
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.js
ย 
๋‹ค์Œ์œผ๋กœ๋Š” 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.js
ย 
๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ 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;
App.js
ย 
์œ„์™€ ๊ฐ™์ด ์ฒดํฌ๋ฐ•์Šค์— ์‚ฌ์šฉ๋  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> </> ); }
App.js
ย 
๋จผ์ € ์‚ฌ์šฉ์ž์—๊ฒŒ ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก input ํƒœ๊ทธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์ฒดํฌ ๋ฐ•์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด type ์†์„ฑ์„ โ€˜checkboxโ€™๋กœ ์ง€์ •ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญ ํ•จ์— ๋”ฐ๋ผ ํ…์ŠคํŠธ๋ฅผ ๋ณ€๊ฒฝ์‹œ์ผœ์ฃผ๊ธฐ ์œ„ํ•ด onChange ์ด๋ฒคํŠธ์— setIsChecked ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ๊ณ , ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ•  ๋•Œ๋งˆ๋‹ค isChecked์˜ ๊ฐ’์ด ๋ฐ”๋€Œ์–ด ํ…์ŠคํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 15-7๊ทธ๋ฆผ 15-7
๊ทธ๋ฆผ 15-7
ย 
์‹คํ–‰ ํ™”๋ฉด์„ ํ™•์ธํ•ด๋ณด๋ฉด ์œ„์™€ ๊ฐ™์ด ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” โ€œ์•„๋‹ˆ์š”โ€๋ผ๋Š” ํ…์ŠคํŠธ๊ฐ€ ํ™•์ธ๋ฉ๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 15-8๊ทธ๋ฆผ 15-8
๊ทธ๋ฆผ 15-8
ย 
์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•˜๋ฉด ์œ„์™€ ๊ฐ™์ด โ€œ๋„คโ€๋ผ๋Š” ํ…์ŠคํŠธ๋กœ ๋ณ€๊ฒฝ๋˜๋ฉฐ, ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ•  ๋•Œ๋งˆ๋‹ค ํ…์ŠคํŠธ๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ 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> ); }
App.js
ย 
๋ฒ„ํŠผ ํƒœ๊ทธ์— onClick ์ด๋ฒคํŠธ๋ฅผ ์ฃผ์–ด setListOpen ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ค‘๊ด„ํ˜ธ ์•ˆ์— ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ state ๋ณ€์ˆ˜ isListOpen๊ณผ ul ํƒœ๊ทธ ์•ˆ์— ๊ฐ์‹ธ์ธ li ํƒœ๊ทธ๋“ค์„ ํ•จ๊ป˜ ์ž‘์„ฑํ•ด์„œ ์กฐ๊ฑด๋ถ€๋กœ ๋ Œ๋”๋ง ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํฌํ•จ๋œ ๋ฒ„ํŠผ์ด ํด๋ฆญ๋  ๋•Œ๋งˆ๋‹ค ํ† ๊ธ€์˜ ์ƒํƒœ๊ฐ€ ์ „ํ™˜๋˜์–ด ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋ณด์ด๊ธฐ๋„, ์ˆจ๊ฒจ์ง€๊ธฐ๋„ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 15-9๊ทธ๋ฆผ 15-9
๊ทธ๋ฆผ 15-9
ย 
๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ธฐ ์ „์—๋Š” ์œ„์™€ ๊ฐ™์ด ๋ฆฌ์ŠคํŠธ๊ฐ€ ํ™•์ธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์Œ๋ฃŒ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋ณด์ด๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํฌํ•จ๋œ ๋ฒ„ํŠผ์ด ํด๋ฆญ๋  ๋•Œ๋งˆ๋‹ค ๋ฐ˜๋ณต์ ์œผ๋กœ ํ† ๊ธ€์˜ ์ƒํƒœ๊ฐ€ ์Šค์œ„์น˜ ์—ญํ• ์„ ํ•˜๋ฉฐ ๋ฐ˜๋Œ€ ๊ฐ’์œผ๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 15-10๊ทธ๋ฆผ 15-10
๊ทธ๋ฆผ 15-10
ย 
์ง€๊ธˆ๊นŒ์ง€ useToggle Hook์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒ„ํŠผ์„ ํด๋ฆญ ํ•จ์— ๋”ฐ๋ผ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋ณด์ด๊ณ  ์ˆจ๊ฒจ์ง€๋Š” ๋‘ ๋ฒˆ์งธ ์˜ˆ์ œ๊นŒ์ง€ ํ™•์ธํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ˜๋Œ€ ๊ฐ’์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, useToggle ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค์–ด ์žฌ์‚ฌ์šฉ ํ•œ๋‹ค๋ฉด ํ† ๊ธ€์„ ๊ด€๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋งˆ๋‹ค ๋™์ผํ•œ ๋กœ์ง์„ ๋ฐ˜๋ณตํ•  ํ•„์š” ์—†์ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
์œ„์—์„œ ์ž‘์„ฑํ–ˆ๋˜ ๋‘ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ App ํ•จ์ˆ˜์— ๊ฐ™์ด ์ž‘์„ฑํ•ด ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์‹คํ–‰ ํ™”๋ฉด์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ตœ์ข… ์ฝ”๋“œ๋Š” ํ•˜๋‹จ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ทธ๋ฆผ 15-11๊ทธ๋ฆผ 15-11
๊ทธ๋ฆผ 15-11
ย 
์ตœ์ข… ์ฝ”๋“œ
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;
App.js
import { useState } from "react"; const useToggle = (initialValue = false) => { const [value, setValue] = useState(initialValue); const toggleValue = () => { setValue(!value) }; return [value, toggleValue]; }; export default useToggle;
useToggle.js
ย 

15.7 (์‹ค์Šต4) useAxios

ย 

15.7.1 axios๋ž€?

ย 
๋จผ์ € axios๋ž€, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›น์„œ๋ฒ„์— ์‚ฌ์šฉ์ž ์š”์ฒญ์˜ ๋ชฉ์ /์ข…๋ฅ˜๋ฅผ ์•Œ๋ฆฌ๋Š” ์ˆ˜๋‹จ์ธ HTTP ๋ฉ”์„œ๋“œ์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ ํ†ต์‹ ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
HTTP ๋ฉ”์„œ๋“œ์—๋Š” get,post,put,delete์™€ ๊ฐ™์ด ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  1. get : ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  1. post : ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  1. put : ๊ธฐ์กด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  1. 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 post ์š”์ฒญ ์˜ˆ์‹œ
๋งŒ์•ฝ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด axios์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ ์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ get ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ 
๋‘ ๋ฒˆ์งธ ์ธ์ž์˜ ํ”„๋กœํผํ‹ฐ๋กœ method๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์œ„์™€ ๊ฐ™์€ ๊ฒฐ๊ด๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
axios(`https://jsonplaceholder.typicode.com/posts`, { method: 'POST', headers: { accept: '*/*' }, data: { userId: 1, id: 19392, title: 'title', body: 'Sample text', }, })
axios post ์š”์ฒญ ๋‹ค๋ฅธ ์˜ˆ์‹œ
๊ทธ๋ ‡๋‹ค๋ฉด ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์‹ค์ œ๋กœ 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;
App.jsx
์œ„์˜ ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด fetchData๋ฅผ ํ†ตํ•ด url๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋’ค ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™”๋ฉด์— ๋ Œ๋”๋งํ•ด์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
notion imagenotion image
ย 
์˜ˆ์ œ์™€ ๊ฐ™์ด ๋‹จ ํ•œ ๋ฒˆ 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.jsx
์œ„์˜ 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;
App.jsx
์œ„์™€ ๊ฐ™์ด ๊ธฐ์กด์—๋Š” ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ์กด์žฌํ•˜๋˜ axios ์š”์ฒญ์„ useAxios๋กœ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•œ๋ˆˆ์— ๋ณด์•„๋„ ์ฝ”๋“œ๊ฐ€ ๋งค์šฐ ๊น”๋”ํ•ด์ง„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ œ์—์„œ ๋ณด์ด๋“ฏ ์ปค์Šคํ…€ ํ›…์„ ํ†ตํ•ด ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋Š” ๊ณง ์œ ์ง€๋ณด์ˆ˜์—๋„ ๊ต‰์žฅํžˆ ์šฉ์ดํ•ด์ง‘๋‹ˆ๋‹ค. ์ด์™€๊ฐ™์ด ์ปค์Šคํ…€ ํ›…์„ ํ™œ์šฉํ•˜๋ฉด ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.