๐Ÿ“

12. Hook - useEffect

๊ฐ„๋‹จํ•œ ์นด์šดํ„ฐ ๋งŒ๋“ค๊ธฐ

cra๋ฅผ ํ†ตํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  App.js๋ฅผ ์•„๋ž˜์™€๊ฐ™์ด ๋งŒ๋“ค์–ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.
function App() { return ( <div> </div> ); }
๊ทธ๋ฆฌ๊ณ  ์นด์šดํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0) const countUp =(e)=>{ setCount(count+1) } return( <> <div>{count}</div> <button onClick={countUp}>up!</button> </> ) } function App() { return ( <div> <Counter/> </div> ); } export default App;

useEffect

count๊ฐ€ ์ปดํฌ๋„ŒํŠธ์˜ state๋กœ ์กด์žฌํ•˜๋Š”๋ฐ ์ด state๊ฐ€ ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค ๋ญ”๊ฐ€ ๋‹ค๋ฅธ ํšจ๊ณผ๋ฅผ ์ฃผ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•˜์—ฌ count๊ฐ€ ํ™€์ˆ˜์ธ์ง€ ์ง์ˆ˜์ธ์ง€ ๋น„๊ตํ•ด์„œ alert์„ ๋„์›Œ์ฃผ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
import React, { useState, useEffect } from 'react';//useEffect์ถ”๊ฐ€ function Counter() { const [count, setCount] = useState(0) const countUp =()=>{ setCount(count+1) } //count๊ฐ€ ๋ณ€ํ–ˆ์„๋•Œ ๋™์ž‘ํ•  ํ–‰๋™์„ useEffect๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„ useEffect(() => { if(count%2){ alert("ํ™€์ˆ˜์ž…๋‹ˆ๋‹ค") }else{ alert("์ง์ˆ˜์ž…๋‹ˆ๋‹ค") } }, [count]) return( <> <div>{count}</div> <button onClick={countUp}>up!</button> </> ) } function App() { return ( <div> <Counter/> </div> ); } export default App;
ย 
useEffect๋ผ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. useState์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ useEffect๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด importํ•ฉ๋‹ˆ๋‹ค. ์ด useEffect๋Š” state๋ฅผ ์ง€์ •ํ•˜์—ฌ ํ•ด๋‹น ์Šคํ…Œ์ดํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Œ์„ ๊ฐ์ง€ํ•˜๋ฉด ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ์ค๋‹ˆ๋‹ค.
์ž, ์—ฌ๊ธฐ์„œ ํ•œ ๋ฒˆ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจ ํ•ด๋ด…์‹œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํด๋ฆญํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ๋„ "์ง์ˆ˜์ž…๋‹ˆ๋‹ค!"๋ผ๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜์˜ต๋‹ˆ๋‹ค. ์ด์œ ๋Š” ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ useEffect๊ฐ€ ์ตœ์ดˆํ•œ๋ฒˆ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ฆ‰ ํ•œ๋ฒˆ ์‹คํ–‰ ํ›„, ์˜์กด์„ฑ ๋ฐฐ์—ด์— ์žˆ๋Š” ๊ฐ’์ด ๋ณ€ํ• ๋•Œ(๋˜๋Š” ๋ Œ๋”๋ง๋งˆ๋‹ค) effect๊ฐ€ ์ผ์–ด๋‚˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค..
ย 
useEffect๋ฅผ ์กฐ๊ธˆ ๋” ์‚ดํŽด๋ด…์‹œ๋‹ค. ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋Š” ์•„๋ž˜์™€๊ฐ™์Šต๋‹ˆ๋‹ค.
useEffect(()=>{ // state๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด ๋ Œ๋”๋ง ๋ ๋•Œ ์‹คํ–‰ํ•˜๋Š” ๋ถ€๋ถ„! // ๊ณต๋ถ€ํ•˜๋ ค๊ณ  ์ฑ… ํŽด๋Š” ํƒ€์ด๋ฐ! return()=>{ // ๋‹ค์‹œ ๋ Œ๋”๋ง์„ ํ•˜๊ธฐ ์ด์ „์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง€์šฐ๊ณ  ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ฒ ์ฃ ? // ์ด ๊ณผ์ •์—์„œ ์ง€์šฐ๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค! clean-up์ด๋ผ๊ณ ๋„ ํ•˜์ฃ . // ์—ฌ๋Ÿฌ๋ถ„๋“ค ์‹œํ—˜ ๊ณต๋ถ€ ํ•˜๋‚˜๋ฅผ ๋งˆ์น˜๊ณ  ๋‹ค์Œ ์‹œํ—˜ ๊ณต๋ถ€ ์ „์— ์ฑ…์ƒ ์ •๋ฆฌํ•˜๋Š” ๋Š๋‚Œ์ด๋ž„๊นŒ์š”.. } },[/*state๊ฐ’์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.(๋“ค์–ด๊ฐ€์ง€ ์•Š์œผ๋ฉด ์ตœ์ดˆ 1๋ฒˆ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.*/)])
ย 

ํ€ด์ฆˆ!

์ตœ์ดˆ๋กœ ๋ Œ๋”๋ง ๋  ๋•Œ, ์ƒํƒœ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋์„ ๋•Œ, ์—…๋ฐ์ดํŠธ๊ฐ€ ๋œ ๋‚ด์šฉ์„ ๋ Œ๋”๋ง ํ•  ๋•Œ log๋ฅผ ์ฐ๋„๋ก ํ•ด๋ณด์„ธ์š”!
ย 

์‹ค์ œ ์ ์šฉํ•ด๋ณด๊ธฐ(useEffect) โ‘ 

useEffect์— ์ž‘์„ฑํ•œ ์•Œ๋ฆผ์ด ํŽ˜์ด์ง€ ๋“ค์–ด๊ฐ€์ž๋งˆ์ž ๋‚˜์™€ ๋ถˆํŽธํ•ฉ๋‹ˆ๋‹ค.
(Hint : useEffect๋ฅผ ์ˆ˜์ •ํ•ด ๋ณด์„ธ์š”. useState๋ฅผ ํ™œ์šฉํ•˜์…”๋„ ์ข‹์Šต๋‹ˆ๋‹ค.)
์ •๋‹ต
์ฒ˜์Œ ์ƒํƒœ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๊ณ ๋‚œ ์ดํ›„์—๋งŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก checkํ• ์ˆ˜์žˆ๋Š” ์ƒํƒœ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
import React, { useState, useEffect } from 'react'; function Counter() { const [count, setCount] = useState(0) const [checkRender, setCheckRender] = useState(false); const countUp =()=>{ setCount(count+1) } useEffect(() => { if (checkRender) { if(count%2){ alert("ํ™€์ˆ˜์ž…๋‹ˆ๋‹ค") }else{ alert("์ง์ˆ˜์ž…๋‹ˆ๋‹ค") } } setCheckRender(true); }, [count]) return( <> <div>{count}</div> <button onClick={countUp}>up!</button> </> ) } function App() { return ( <div> <Counter/> </div> ); } export default App;

์‹ค์ œ ์ ์šฉํ•ด๋ณด๊ธฐ(useEffect, cleanup) โ‘ก

notion imagenotion image
Date ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์™€๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์ถ”๊ฐ€ํ•˜๊ณ ,
function Time(props) { const [today, setToday] = useState(new Date()); const [hour, setHour] = useState(today.getHours()); const [min, setMin] = useState(today.getMinutes()); const [sec, setSec] = useState(today.getSeconds()); console.log("๋ Œ๋”๋ง์ด ๋ฉ๋‹ˆ๋‹ค..?")//๋ Œ๋”๋ง์ด ์ž˜ ๋˜๋Š”์ง€ ํ™•์ธ์šฉ! ๊ผญ ๋„ฃ๊ณ  ์ง„ํ–‰ํ•ด์ฃผ์„ธ์š”. return ( <div> <h1> ์‹œ๊ฐ„ : {hour}์‹œ {min}๋ถ„ {sec}์ดˆ </h1> </div> ); } function App() { return ( <div> <Counter/> <Time/> </div> ); }
์‹œ๊ฐ„์„ ์ƒˆ๋กœ๊ณ ์นจํ•˜์ง€ ์•Š์•„๋„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ”๋€Œ๊ฒŒ ํ•ด๋ณด์„ธ์š” :)
์ •๋‹ต
์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜์…จ๋‹ค๋ฉด Time์ปดํฌ๋„ŒํŠธ์—์„œ ๋กœ๊ทธ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ •๋ง ๋งŽ์€ ํšŸ์ˆ˜์˜ ๋กœ๊ทธ๋ฅผ ๋ณด์‹ค ์ˆ˜ ์žˆ์„๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€, useEffect๋ฅผ ์ด์šฉํ–ˆ๋‹ค ํ•ด๋„ ๋งŒ์•ฝ cleanup์„ ์ด์šฉํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฌด์ˆ˜ํ•œ ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚˜๊ณ ์žˆ์Œ์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
function Time(props) { const [today, setToday] = useState(new Date()); const [hour, setHour] = useState(today.getHours()); const [min, setMin] = useState(today.getMinutes()); const [sec, setSec] = useState(today.getSeconds()); console.log("๋ Œ๋”๋ง์ด ๋ฉ๋‹ˆ๋‹ค..?") setInterval(() => { const t = new Date(); setToday(t); setHour(t.getHours()); setMin(t.getMinutes()); setSec(t.getSeconds()); }, 1000); return ( <div> <h1> ์‹œ๊ฐ„ : {hour}์‹œ {min}๋ถ„ {sec}์ดˆ </h1> </div> ); } function App() { return ( <div> <Counter/> <Time/> </div> ); }
useEffect ์‚ฌ์šฉํ•˜๊ธฐ ์ „
๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” cleanup์ด๋ž€๊ฒƒ์„ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค!
setinterval ์„ ํ•˜๊ฒŒ๋˜๋ฉด 1์ดˆ์— ํ•œ๋ฒˆ ๊ฐ™์€ ๋™์ž‘์„ ๋ฐ˜๋ณตํ•˜๊ฒŒ ๋ ํ…๋ฐ์š”, ์ด 1์ดˆ์— ํ•˜๋Š”์ผ์„ ๊ณ„์† ์ถ”๊ฐ€ํ•ด์„œ 1์ดˆ์— ์ˆ˜๋ฒˆ(setintervalํ•œ ํšŸ์ˆ˜๋งŒํผ)์˜ ๊ฐ™์€์ผ์„ ํ•˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, setState๋ฅผ ํ•˜๋Š” ํšŸ์ˆ˜๊ฐ€ ๊ณ„์† ์ถ”๊ฐ€๋˜๋Š”๊ฑฐ์ฃ . ๊ทธ๋Ÿฌ๋‹ˆ ์šฐ๋ฆฌ๋Š” 1์ดˆ๋งˆ๋‹ค(์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์ง€๊ธฐ ์ง์ „) ๋ฐ˜๋ณตํ•ด์ฃผ๋Š” ๋™์ž‘์„ ์‚ญ์ œํ•ด์ฃผ๋Š” ์ผ์„ ํ•ด์ฃผ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์™€๊ฐ™์ด ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค!
import { useState, useEffect } from "react"; function Time(props) { const [today, setToday] = useState(new Date()); const [hour, setHour] = useState(today.getHours()); const [min, setMin] = useState(today.getMinutes()); const [sec, setSec] = useState(today.getSeconds()); console.log("๋ Œ๋”๋ง์ด ๋ฉ๋‹ˆ๋‹ค..?") useEffect(() => { let time = setInterval(() => { const t = new Date(); setToday(t); setHour(t.getHours()); setMin(t.getMinutes()); setSec(t.getSeconds()); }, 1000); return () => { //์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์ง€๊ธฐ ์ „์— setinterval์„ clearintervalํ•ด์ค๋‹ˆ๋‹ค clearInterval(time); }; }, [today]); return ( <div> <h1> ์‹œ๊ฐ„ : {hour}์‹œ {min}๋ถ„ {sec}์ดˆ </h1> </div> ); } export default Time;
useEffect ์‚ฌ์šฉ ํ›„
// ์ฝ”๋“œ ๋ฆฌํŽ™ํ† ๋ง import { useState, useEffect } from "react"; function Time(props) { const [today, setToday] = useState(new Date()); const hour = today.getHours(); const min = today.getMinutes(); const sec = today.getSeconds(); console.log("๋ Œ๋”๋ง์ด ๋ฉ๋‹ˆ๋‹ค..?") useEffect(() => { let time = setInterval(() => { const t = new Date(); setToday(t); }, 1000); return () => { clearInterval(time); }; }, [today]); return ( <div> <h1> ์‹œ๊ฐ„ : {hour}์‹œ {min}๋ถ„ {sec}์ดˆ </h1> </div> ); } export default Time;
ย 
ย