Ref๋ก ๊ฐ ์ฐธ์กฐํ๊ธฐ
์ปดํฌ๋ํธ๊ฐ ์ผ๋ถ ์ ๋ณด๋ฅผ โ๊ธฐ์ตโํ๊ณ ์ถ์ง๋ง, ํด๋น ์ ๋ณด๊ฐ ๋ ๋๋ง์ ์ ๋ฐํ์ง ์๋๋ก ํ๋ ค๋ฉด Ref๋ฅผ ์ฌ์ฉํ์ธ์.
ํ์ต ๋ด์ฉ
- ์ปดํฌ๋ํธ Ref๋ฅผ ์ด๋ป๊ฒ ์ถ๊ฐํ๋๊ฐ
- Ref์ ๊ฐ์ด ์ด๋ป๊ฒ ์ ๋ฐ์ดํธ๋๋๊ฐ
- Ref๊ฐ State์ ์ด๋ป๊ฒ ๋ค๋ฅธ๊ฐ
- Ref๋ฅผ ์ด๋ป๊ฒ ์์ ํ๊ฒ ์ฌ์ฉํ ๊น
์ปดํฌ๋ํธ์ Ref๋ฅผ ์ถ๊ฐํ๊ธฐ
React์์ useRef
Hook์ ๊ฐ์ ธ์ ์ปดํฌ๋ํธ์ Ref๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
import { useRef } from 'react';
์ปดํฌ๋ํธ ๋ด์์ useRef
Hook์ ํธ์ถํ๊ณ ์ฐธ์กฐํ ์ด๊น๊ฐ์ ์ ์ผํ ์ธ์๋ก ์ ๋ฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ค์์ ๊ฐ 0
์ ๋ํ Ref์
๋๋ค.
const ref = useRef(0);
useRef
๋ ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
{
current: 0 // useRef์ ์ ๋ฌํ ๊ฐ
}

Illustrated by Rachel Lee Nabors
ref.current
ํ๋กํผํฐ๋ฅผ ํตํด ํด๋น Ref์ current
๊ฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ด ๊ฐ์ ์๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์์ผ๋ฏ๋ก ์ฝ๊ณ ์ธ ์ ์์ต๋๋ค. React๊ฐ ์ถ์ ํ์ง ์๋ ๊ตฌ์ฑ ์์์ ๋น๋ฐ ์ฃผ๋จธ๋๋ผ ํ ์ ์์ต๋๋ค. (์ด๊ฒ์ด ๋ฐ๋ก React์ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์์ โํ์ถ๊ตฌโ๊ฐ ๋๋ ๊ฒ์
๋๋ค. ์๋์์ ์์ธํ ์ค๋ช
ํ๊ณ ์์ต๋๋ค!)
์ฌ๊ธฐ์ ๋ฒํผ์ ํด๋ฆญํ ๋๋ง๋ค ref.current
๋ฅผ ์ฆ๊ฐ์ํต๋๋ค.
import { useRef } from 'react'; export default function Counter() { let ref = useRef(0); function handleClick() { ref.current = ref.current + 1; alert('You clicked ' + ref.current + ' times!'); } return ( <button onClick={handleClick}> Click me! </button> ); }
Ref๋ ์ซ์๋ฅผ ๊ฐ๋ฆฌํค์ง๋ง, State์ฒ๋ผ ๋ฌธ์์ด, ๊ฐ์ฒด, ์ฌ์ง์ด ํจ์ ๋ฑ ๋ชจ๋ ๊ฒ์ ๊ฐ๋ฆฌํฌ ์ ์์ต๋๋ค. State์ ๋ฌ๋ฆฌ Ref๋ ์ฝ๊ณ ์์ ํ ์ ์๋ current
ํ๋กํผํฐ๋ฅผ ๊ฐ์ง ์ผ๋ฐ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์
๋๋ค.
์ปดํฌ๋ํธ๋ ๋ชจ๋ ์ฆ๊ฐ์ ๋ํ์ฌ ๋ค์ ๋ ๋๋ง ๋์ง ์์ต๋๋ค. State์ ๋ง์ฐฌ๊ฐ์ง๋ก Ref๋ React์ ๋ฆฌ๋ ๋์ ์ํด ์ ์ง๋ฉ๋๋ค. ๊ทธ๋ฌ๋, State๋ฅผ ์ค์ ํ๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋ ๋๋ง ๋ฉ๋๋ค. Ref๋ฅผ ๋ณ๊ฒฝํ๋ฉด ๋ค์ ๋ ๋๋ง ๋์ง ์์ต๋๋ค!
์์: ์คํฑ์์น ์์ฑํ๊ธฐ
Ref์ State๋ฅผ ๋จ์ผ ์ปดํฌ๋ํธ๋ก ๊ฒฐํฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ๋๋ฌ ์์ํ๊ฑฐ๋ ์ค์งํ ์ ์๋ ์คํฑ์์น๋ฅผ ๋ง๋ค์ด๋ด ์๋ค. ์ฌ์ฉ์๊ฐ โ์์โ์ ๋๋ฅธ ํ ์๊ฐ์ด ์ผ๋ง๋ ์ง๋ฌ๋์ง ํ์ํ๋ ค๋ฉด ์์ ๋ฒํผ์ ๋๋ฅธ ์๊ธฐ์ ํ์ฌ ์๊ฐ์ ์ถ์ ํด์ผ ํฉ๋๋ค. ์ด ์ ๋ณด๋ ๋ ๋๋ง์ ์ฌ์ฉ๋๋ฏ๋ก State๋ฅผ ์ ์งํฉ๋๋ค.
const [startTime, setStartTime] = useState(null);
const [now, setNow] = useState(null);
์ฌ์ฉ์๊ฐ โ์์โ์ ๋๋ฅด๋ฉด setInterval
์ ์ฌ์ฉํ์ฌ 10๋ฐ๋ฆฌ์ด๋ง๋ค ์๊ฐ์ ์
๋ฐ์ดํธํฉ๋๋ค.
import { useState } from 'react'; export default function Stopwatch() { const [startTime, setStartTime] = useState(null); const [now, setNow] = useState(null); function handleStart() { // ์นด์ดํ ์ ์์ํฉ๋๋ค. setStartTime(Date.now()); setNow(Date.now()); setInterval(() => { // 10ms ๋ง๋ค ํ์ฌ ์๊ฐ์ ์ ๋ฐ์ดํธ ํฉ๋๋ค. setNow(Date.now()); }, 10); } let secondsPassed = 0; if (startTime != null && now != null) { secondsPassed = (now - startTime) / 1000; } return ( <> <h1>Time passed: {secondsPassed.toFixed(3)}</h1> <button onClick={handleStart}> Start </button> </> ); }
โStopโ ๋ฒํผ์ ๋๋ฅด๋ฉด now
State ๋ณ์์ ์
๋ฐ์ดํธ๋ฅผ ์ค์งํ๊ธฐ ์ํด ๊ธฐ์กด Interval์ ์ทจ์ํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ์ํด clearInterval
์ ํธ์ถํ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด์ ์ ์ฌ์ฉ์๊ฐ ์์์ ๋๋ ์ ๋ setInterval
ํธ์ถ๋ก ๋ฐํ๋ interval ID๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. Interval ID๋ ์ด๋๊ฐ์ ๋ณด๊ดํด์ผ ํฉ๋๋ค. Interval ID๋ ๋ ๋๋ง์ ์ฌ์ฉํ์ง ์์ผ๋ฏ๋ก Ref์ ์ ์ฅํ ์ ์์ต๋๋ค.
import { useState, useRef } from 'react'; export default function Stopwatch() { const [startTime, setStartTime] = useState(null); const [now, setNow] = useState(null); const intervalRef = useRef(null); function handleStart() { setStartTime(Date.now()); setNow(Date.now()); clearInterval(intervalRef.current); intervalRef.current = setInterval(() => { setNow(Date.now()); }, 10); } function handleStop() { clearInterval(intervalRef.current); } let secondsPassed = 0; if (startTime != null && now != null) { secondsPassed = (now - startTime) / 1000; } return ( <> <h1>Time passed: {secondsPassed.toFixed(3)}</h1> <button onClick={handleStart}> Start </button> <button onClick={handleStop}> Stop </button> </> ); }
๋ ๋๋ง์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ ๋ ํด๋น ์ ๋ณด๋ฅผ State๋ก ์ ์งํฉ๋๋ค. ์ด๋ฒคํธ ํธ๋ค๋ฌ์๊ฒ๋ง ํ์ํ ์ ๋ณด์ด๊ณ ๋ณ๊ฒฝ์ด ์ผ์ด๋ ๋ ๋ฆฌ๋ ๋๋ง์ด ํ์ํ์ง ์๋ค๋ฉด, Ref๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ํจ์จ์ ์ผ ์ ์์ต๋๋ค.
Ref์ State์ ์ฐจ์ด
Ref๊ฐ State๋ณด๋ค ๋ โ์๊ฒฉํโ ๊ฒ์ผ๋ก ์๊ฐ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ํญ์ State ์ค์ ํจ์๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ํ์ง๋ง ๋๋ถ๋ถ์ State๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. Ref๋ ์์ฃผ ํ์ํ์ง ์์ โํ์ถ๊ตฌโ์ ๋๋ค. State์ Ref๋ฅผ ๋น๊ตํ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Ref | State |
---|---|
useRef(initialValue) ๋ { current: initialValue } ๋ฅผ ๋ฐํํฉ๋๋ค. | useState(initialValue) ๋ State ๋ณ์์ ํ์ฌ ๊ฐ๊ณผ Setter ํจ์ [value, setValue] ๋ฅผ ๋ฐํํฉ๋๋ค. |
current ๊ฐ์ ๋ฐ๊ฟ๋ ๋ฆฌ๋ ๋๋ง ํ์ง ์์ต๋๋ค. | State๋ฅผ ๋ฐ๊พธ๋ฉด ๋ฆฌ๋ ๋๋ง ํฉ๋๋ค. |
Mutable: ๋ ๋๋ง ํ๋ก์ธ์ค ์ธ๋ถ์์ current ๊ฐ์ ์์ ๋ฐ ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค. | Immutable: State๋ฅผ ์์ ํ๊ธฐ ์ํด์๋ State ์ค์ ํจ์๋ฅผ ๋ฐ๋์ ์ฌ์ฉํ์ฌ ๋ฆฌ๋ ๋๋ง ๋๊ธฐ์ด์ ๋ฃ์ด์ผ ํฉ๋๋ค. |
๋ ๋๋ง ์ค์๋ current ๊ฐ์ ์ฝ๊ฑฐ๋ ์ฐ๋ฉด ์ ๋ฉ๋๋ค. | ์ธ์ ๋ ์ง State๋ฅผ ์ฝ์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ ๋ ๋๋ง๋ง๋ค ๋ณ๊ฒฝ๋์ง ์๋ ์์ฒด์ ์ธ State์ Snapshot์ด ์์ต๋๋ค. |
๋ค์์ State์ ํจ๊ป ๊ตฌํํ ์นด์ดํฐ ๋ฒํผ์ ๋๋ค.
import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <button onClick={handleClick}> You clicked {count} times </button> ); }
count
๊ฐ์ ํ์ํ๋ฏ๋ก State ๊ฐ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํ๋นํฉ๋๋ค. ์นด์ดํฐ์ ๊ฐ์ setCount()
๋ก ์ค์ ํ๋ฉด React๋ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํ๊ณ ์ ์นด์ดํธ๋ฅผ ๋ฐ์ํ๋๋ก ํ๋ฉด์ ์
๋ฐ์ดํธํฉ๋๋ค.
์ด๋ฅผ Ref์ ํจ๊ป ๊ตฌํํ๋ ค๊ณ ํ๋ฉด React๋ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํ์ง ์์ผ๋ฏ๋ก ์นด์ดํธ๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค! ์ด ๋ฒํผ์ ํด๋ฆญํด๋ ํ ์คํธ๋ฅผ ์ ๋ฐ์ดํธํ์ง ์๋ ๋ฐฉ๋ฒ์ ํ์ธํด๋ด ์๋ค.
import { useRef } from 'react'; export default function Counter() { let countRef = useRef(0); function handleClick() { // ์ด๊ฒ์ ์ปดํฌ๋ํธ์ ๋ฆฌ๋ ๋๋ฅผ ์ผ์ผํค์ง ์์ต๋๋ค! countRef.current = countRef.current + 1; } return ( <button onClick={handleClick}> You clicked {countRef.current} times </button> ); }
์ด๊ฒ์ด ๋ ๋๋ง ์ค์ ref.current
๋ฅผ ์ถ๋ ฅํ๋ฉด ์ ๋ขฐํ ์ ์๋ ์ฝ๋๊ฐ ๋์ค๋ ์ด์ ์
๋๋ค. ์ด ๋ถ๋ถ์ด ํ์ํ๋ฉด State๋ฅผ ๋์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
์์ธํ ์ดํด๋ณด๊ธฐ
React๊ฐ useState
์ useRef
๋ฅผ ๋ชจ๋ ์ ๊ณตํ์ง๋ง, ์์น์ ์ผ๋ก useRef
๋ useState
์์ ๊ตฌํํ ์ ์์ต๋๋ค. React ๋ด๋ถ์์ useRef
๋ฅผ ์ด๋ ๊ฒ ๊ตฌํํ๋ ๊ฒ์ ์์ํ ์ ์์ต๋๋ค.
// Inside of React
function useRef(initialValue) {
const [ref, unused] = useState({ current: initialValue });
return ref;
}
์ฒซ ๋ฒ์งธ ๋ ๋๋ง ์ค์ useRef
๋ { current: initialValue }
๋ฅผ ๋ฐํํฉ๋๋ค. ์ด ๊ฐ์ฒด๋ React์ ์ํด ์ ์ฅ๋๋ฏ๋ก ๋ค์ ๋ ๋๋ง ์ค์ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ์ด ์์์์๋ State Setter๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ ์ ์ฃผ๋ชฉํ์ธ์. useRef
๋ ํญ์ ๋์ผํ ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผ ํ๋ฏ๋ก ํ์ํ์ง ์์ต๋๋ค!
React๋ useRef
๊ฐ ์ค์ ๋ก ์ถฉ๋ถํ ์ผ๋ฐ์ ์ด๊ธฐ ๋๋ฌธ์ built-in ๋ฒ์ ์ ์ ๊ณตํฉ๋๋ค. setter๊ฐ ์๋ ์ผ๋ฐ์ ์ธ state ๋ณ์๋ผ๊ณ ์๊ฐํ ์ ์์ต๋๋ค. ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ต์ํ๋ค๋ฉด Ref๋ ์ธ์คํด์ค ํ๋๋ฅผ ์๊ธฐ์ํฌ ์ ์์ต๋๋ค. ํ์ง๋ง this.something
๋์ ์ somethingRef.current
์ฒ๋ผ ์จ์ผํฉ๋๋ค.
Ref๋ฅผ ์ฌ์ฉํ ์๊ธฐ
์ผ๋ฐ์ ์ผ๋ก ์ปดํฌ๋ํธ๊ฐ React๋ฅผ โ์ธ๋ถโ์ ์ธ๋ถ APIโ์ปดํฌ๋ํธ์ ํํ์ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๋ธ๋ผ์ฐ์ API ์ ํต์ ํด์ผ ํ ๋ Ref๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ค์์ ๋ช ๊ฐ์ง ํน๋ณํ ์ํฉ์ ๋๋ค.
- Timeout ID๋ฅผ ์ ์ฅ
- ๋ค์ ํ์ด์ง์์ ๋ค๋ฃจ๋ DOM ์๋ฆฌ๋จผํธ ์ ์ฅ ๋ฐ ์กฐ์
- JSX๋ฅผ ๊ณ์ฐํ๋ ๋ฐ ํ์ํ์ง ์์ ๋ค๋ฅธ ๊ฐ์ฒด ์ ์ฅ
์ปดํฌ๋ํธ๊ฐ ์ผ๋ถ ๊ฐ์ ์ ์ฅํด์ผ ํ์ง๋ง ๋ ๋๋ง ๋ก์ง์ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๊ฒฝ์ฐ, Ref๋ฅผ ์ ํํฉ๋๋ค.
Ref์ ์ข์ ์์
๋ค์ ์์น์ ๋ฐ๋ฅด๋ฉด ์ปดํฌ๋ํธ๋ฅผ ๋ณด๋ค ์ฝ๊ฒ ์์ธกํ ์ ์์ต๋๋ค.
- Ref๋ฅผ ํ์ถ๊ตฌ๋ก ๊ฐ์ฃผํฉ๋๋ค. Ref๋ ์ธ๋ถ ์์คํ ์ด๋ ๋ธ๋ผ์ฐ์ API๋ก ์์ ํ ๋ ์ ์ฉํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง๊ณผ ๋ฐ์ดํฐ ํ๋ฆ์ ์๋น ๋ถ๋ถ์ด Ref์ ์์กดํ๋ค๋ฉด ์ ๊ทผ ๋ฐฉ์์ ์ฌ๊ณ ํด ๋ณด๋ ๊ฒ์ด ์ข์ต๋๋ค.
- ๋ ๋๋ง ์ค์
ref.current
๋ฅผ ์ฝ๊ฑฐ๋ ์ฐ์ง ๋ง์ธ์. ๋ ๋๋ง ์ค์ ์ผ๋ถ ์ ๋ณด๊ฐ ํ์ํ ๊ฒฝ์ฐ State๋ฅผ ๋์ ์ฌ์ฉํ์ธ์.ref.current
๊ฐ ์ธ์ ๋ณํ๋์ง React๋ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ๋๋งํ ๋ ์ฝ์ด๋ ์ปดํฌ๋ํธ์ ๋์์ ์์ธกํ๊ธฐ ์ด๋ ต์ต๋๋ค. (if (!ref.current) ref.current = new Thing()
๊ณผ ๊ฐ์ ์ฝ๋๋ ์ฒซ ๋ฒ์งธ ๋ ๋๋ง ์ค์ Ref๋ฅผ ํ ๋ฒ๋ง ์ค์ ํ๋ ๊ฒฝ์ฐ๋ผ ์์ธ์ ๋๋ค.)
React State์ ์ ํ์ Ref์ ์ ์ฉ๋์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด State๋ ๋ชจ๋ ๋ ๋๋ง์ ๋ํ Snapshot ๋ฐ ๋๊ธฐ์ ์ผ๋ก ์
๋ฐ์ดํธ๋์ง ์๋ ๊ฒ๊ณผ ๊ฐ์ด ์๋ํฉ๋๋ค. ๊ทธ๋ฌ๋ Ref์ current
๊ฐ์ ๋ณ์กฐํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฆ์ ๋ณ๊ฒฝ๋ฉ๋๋ค.
ref.current = 5;
console.log(ref.current); // 5
๊ทธ ์ด์ ๋ Ref ์์ฒด๊ฐ ์ผ๋ฐ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์ฒ๋ผ ๋์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋ํ Ref๋ก ์์ ํ ๋ Mutation ๋ฐฉ์ง์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค. ๋ณํํ๋ ๊ฐ์ฒด๋ฅผ ๋ ๋๋ง์ ์ฌ์ฉํ์ง ์๋ ํ, React๋ Ref ํน์ ํด๋น ์ฝํ ์ธ ๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋ ์ ๊ฒฝ ์ฐ์ง ์์ต๋๋ค.
Ref์ DOM
์์์ ๊ฐ์ Ref๋ก ์ง์ ํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ Ref์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก๋ DOM ์๋ฆฌ๋จผํธ์ ์ ๊ทผํ๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์
๋ ฅ์ฐฝ์ ์ด์ ์ ๋ง์ถ๋ ค๋ ๊ฒฝ์ฐ ์ ์ฉํฉ๋๋ค. <div ref={myRef}>
์ ๊ฐ์ JSX์ ref
์ดํธ๋ฆฌ๋ทฐํธ์ Ref๋ฅผ ์ ๋ฌํ๋ฉด React๋ ํด๋น DOM ์๋ฆฌ๋จผํธ๋ฅผ myRef.current
์ ๋ฃ์ต๋๋ค. ๋ง์ฝ ์๋ฆฌ๋จผํธ๊ฐ DOM ์์ ์ฌ๋ผ์ง๋ฉด, React ๋ myRef.current
๊ฐ์ null
๋ก ์
๋ฐ์ดํธ ํฉ๋๋ค. ์ด์ ๋ํ ์์ธํ ๋ด์ฉ์ Ref๋ก DOM ์กฐ์ํ๊ธฐ์์ ํ์ธํ ์ ์์ต๋๋ค.
์์ฝ
- Ref๋ ๋ ๋๋ง์ ์ฌ์ฉ๋์ง ์๋ ๊ฐ์ ๊ณ ์ ํ๊ธฐ ์ํ ํ์ถ๊ตฌ์ด๋ฉฐ, ์์ฃผ ํ์ํ์ง๋ ์์ต๋๋ค.
- Ref๋ ์ฝ๊ฑฐ๋ ์ค์ ํ ์ ์๋
current
๋ผ๋ ํ๋กํผํฐ๋ฅผ ํธ์ถํ ์ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์๊ฐ์ฒด์ ๋๋ค. useRef
Hook์ ํธ์ถํด Ref๋ฅผ ๋ฌ๋ผ๊ณ React์ ์์ฒญํ ์ ์์ต๋๋ค.- State์ ๋ง์ฐฌ๊ฐ์ง๋ก Ref๋ ์ปดํฌ๋ํธ์ ๋ ๋๋ง ๊ฐ์ ์ ๋ณด๋ฅผ ์ ์งํ ์ ์์ต๋๋ค.
- State์ ๋ฌ๋ฆฌ Ref์
current
๊ฐ์ ์ค์ ํ๋ฉด ๋ฆฌ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํ์ง ์์ต๋๋ค. - ๋ ๋๋ง ์ค์
ref.current
๋ฅผ ์ฝ๊ฑฐ๋ ์ฐ์ง ๋ง์ธ์. ์ปดํฌ๋ํธ๋ฅผ ์์ธกํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค.
์ฑ๋ฆฐ์ง 1 of 4: ์ ์์ ์ผ๋ก ๋์ํ์ง ์๋ ์ฑํ
์
๋ ฅ์ฐฝ ์์
๋ฉ์์ง๋ฅผ ์
๋ ฅํ๊ณ โSendโ๋ฅผ ํด๋ฆญํฉ๋๋ค. โSent!โ ๊ฒฝ๊ณ ์ฐฝ(alert)์ด ๋ํ๋๊ธฐ ์ ์ 3์ด ์ ๋ ์ง์ฐ๋๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ด ์ง์ฐ๋ ์๊ฐ ๋์ โUndoโ ๋ฒํผ์ ๋ณผ ์ ์์ต๋๋ค. ๋๋ฅด์ธ์. ์ด โUndoโ ๋ฒํผ์ โSent!โ ๋ฉ์์ง๊ฐ ๋ํ๋์ง ์๋๋ก ํฉ๋๋ค. handleSend
์ค ์ ์ฅ๋ Timeout ID์ ๋ํด clearTimeout
์ ํธ์ถํ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ โUndoโ๋ฅผ ํด๋ฆญํ ํ์๋ โSent!โ ๋ฉ์์ง๊ฐ ๊ณ์ ๋ํ๋ฉ๋๋ค. ์ ์๋ํ์ง ์๋์ง ์ฐพ์์ ๊ณ ์ณ๋ด
์๋ค.
import { useState } from 'react'; export default function Chat() { const [text, setText] = useState(''); const [isSending, setIsSending] = useState(false); let timeoutID = null; function handleSend() { setIsSending(true); timeoutID = setTimeout(() => { alert('Sent!'); setIsSending(false); }, 3000); } function handleUndo() { setIsSending(false); clearTimeout(timeoutID); } return ( <> <input disabled={isSending} value={text} onChange={e => setText(e.target.value)} /> <button disabled={isSending} onClick={handleSend}> {isSending ? 'Sending...' : 'Send'} </button> {isSending && <button onClick={handleUndo}> Undo </button> } </> ); }