React - useRef

2022. 5. 7. 18:24ใ†React

React - useRef

 

https://www.daleseo.com/react-hooks-use-ref/

 

React Hooks: useRef ์‚ฌ์šฉ๋ฒ•

Engineering Blog by Dale Seo

www.daleseo.com

(ํ•ด๋‹น ๊ธ€์€ ์œ„ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ์กฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.)

 

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ๋ฆฌ์•กํŠธ์—์„œ ํŠน์ • ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์œ ์šฉํ•œ ํ•จ์ˆ˜ ํ›…์ธ useRef์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

 

useRef๋Š” ์ธ์ž๋ฅผ ๋„ฃ์–ด ์ •์˜ํ•˜๋ฉด current ๊ฐ’์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด current ๊ฐ’์— ์ธ์ž๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค. 

 

๋ณดํŽธ์ ์œผ๋กœ useRef๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์€ 3๊ฐ€์ง€๋กœ ๋‚˜๋‰œ๋‹ค.

1. ํฌ์ปค์Šค, ํ…์ŠคํŠธ ์„ ํƒ์˜์—ญ, ํ˜น์€ ๋ฏธ๋””์–ด์˜ ์žฌ์ƒ์„ ๊ด€๋ฆฌํ•  ๋•Œ

2. ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ง์ ‘์ ์œผ๋กœ ์‹คํ–‰์‹œํ‚ฌ ๋•Œ

3. ์„œ๋“œ ํŒŒํ‹ฐ DOM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ React์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ๋–„.

 

์„ ์–ธ์ ์œผ๋กœ ํ•ด๊ฒฐ๋  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ(ex. ํ™”์‚ดํ‘œ ์•„์ด์ฝ˜์„ ํ†ตํ•œ ์ œ์–ด)๋Š” ref ์‚ฌ์šฉ์„ ์ง€์–‘ํ•˜๊ณ  props๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐ.

 

ํ•„์ž๋Š” input ์š”์†Œ์— ์—ฐ๊ฒฐ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด๋‚˜ useRef๋กœ ์ธํ•œ ๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹Œ setInterval์™€ ๊ด€๋ จํ•œ ๋‚ด์šฉ์„ ๋‹ค๋ค„๋ณผ ๊ฒƒ์ด๋‹ค. 

 

์šฐ๋ฆฌ๋Š” ์ž๋™์œผ๋กœ ์นด์šดํŠธํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ Œ๋”๋ง์ด ๋˜๊ณ  ๋‚œ ํ›„์— ์ž‘๋™์ด ๋˜๋Š” useEffect ๋‚ด๋ถ€์—์„œ count๊ฐ€ ๋ณ€ํ™”ํ•˜๊ฒŒ ๋˜๊ณ  ์ด๋Š” state๋ณ€ํ™”๋กœ ์ด์–ด์ ธ app ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ๋ Œ๋”๋งํ•˜๊ฒŒ ๋œ๋‹ค. ํ•˜์ง€๋งŒ useEffect์˜ ๋‘๋ฒˆ์งธ ์ธ์ž๋Š” ๋นˆ ๋ฐฐ์—ด์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ถ€๋ถ„์€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค. 

 

๊ทธ๋Ÿผ์—๋„ interValId๋Š” setInterval์ด DomApI๋กœ ์‹คํ–‰๋˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ €์— ๋‚จ์•„์„œ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋‹ค. 

์ž๋™์œผ๋กœ ์นด์šดํŠธํ•˜๋Š” ์ฝ”๋“œ๋กœ๋Š” ์ข‹์•„๋ณด์ด๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

import React, { useState, useEffect } from 'react';


function App() {
  const [count, setCount] = useState(0);
  console.log(`๋ Œ๋”๋ง... count: ${count}`)

  useEffect(() => {
    console.log('useEffect');
    const interValId = setInterval(() => setCount((count) => count +1), 1000);
    return () => clearInterval(interValId);
  }, []);

  return (
    <div>
      <p>์ž๋™ ์นด์šดํŠธ: {count}</p>
    </div>
  );
}

export default App;

 

์ด๋ฒˆ์—๋Š” ์ž๋™์นด์šดํŠธ ๊ธฐ๋Šฅ๊ณผ ๋”๋ถˆ์–ด ์นด์šดํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์ •์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด์ž.

์šฐ์„  intervalId๋Š” ์นด์šดํŠธ๋ฅผ ์‹œ์ž‘์‹œํ‚ค๋Š” ํ•จ์ˆ˜์™€ ์ •์ง€์‹œํ‚ค๋Š” ํ•จ์ˆ˜ ๋‘˜ ๋‹ค ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ƒ๋‹จ์—์„œ ์ •์˜๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค. ์–ผํ• ๋ณด๋ฉด ๋ฌธ์ œ๊ฐ€ ์—†์–ด ๋ณด์ด์ง€๋งŒ intervalId๊ฐ€ ์ •์˜๋œ ๋ฐฉ์‹์„ ์‚ดํŽด๋ณด๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ณด์ธ๋‹ค. 

 

๋จผ์ € startCounterํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผฐ์„ ๋•Œ ์šฐ๋ฆฌ๋Š” count state๋ฅผ ์กฐ์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค. state๊ฐ€ ์กฐ์ž‘๋˜๋ฉด ์žฌ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚˜๊ณ  intervalId๊ฐ€ ๋‹ค์‹œ ์ƒˆ๋กญ๊ฒŒ ์ •์˜๊ฐ€ ๋œ๋‹ค. ์ด๊ฒƒ์ด ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์€ ๊ธฐ์กด์— setInterval์„ ๊ฑธ์–ด๋†“์•˜๋˜ intervalId๊ฐ€ clear๋˜์ง€ ์•Š์€์ƒํƒœ๋กœ ๋ธŒ๋ผ์šฐ์ €์— ๋‚จ์•„์žˆ์„ ๊ฑฐ๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์œ„์˜ useEffect์˜ˆ์‹œ์—์„œ๋Š” intervalId๊ฐ€ ์ „์—ญ์œผ๋กœ ์„ ์–ธ๋˜์–ด์žˆ์ง€ ์•Š์•„์„œ ๋ณ€ํ•˜์ง€ ์•Š์•˜๋˜ ๊ฒŒ ์ด ์˜ˆ์‹œ์—์„œ๋Š” ๊ฑธ๋ฆผ๋Œ์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

import React, { useState, useEffect } from 'react';


function App() {
  const [count, setCount] = useState(0);

  let intervalId; 
  const startCounter = () => {
    intervalId = setInterval(()=> setCount((count) => count+1), 1000);
  };

  const stopCounter = () => {
    clearInterval(intervalId);
  };

  return (
    <div>
      <p>์ž๋™ ์นด์šดํŠธ: {count}</p>
      <button onClick={startCounter}>์‹œ์ž‘</button>
      <button onClick={stopCounter}>์ •์ง€</button>
    </div>
  );
}

export default App;

 

๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋Š” ์ƒ๊ฐํ•˜๊ฒŒ ๋œ๋‹ค. 'intervalId๊ฐ€ ๊ณ„์† ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ €์— ๋‚จ๊ฒŒ๋˜๋ฉด ๋ณ€ํ•˜์ง€ ์•Š๊ฒŒํ•˜๋ฉด ๋˜์ง€ ์•Š์„๊นŒ?'

๊ทธ๋ž˜์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ useRef์ด๋‹ค. 

useRef๋กœ ์ •์˜ ๋œ ๋ณ€์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žฌ๋ Œ๋”๋งํ•  ๋•Œ current ์†์„ฑ์˜ ๊ฐ’์ด ์œ ์‹ค๋˜์ง€ ์•Š๋Š”๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด์ž.

 

import React, { useState, useEffect, useRef } from 'react';


function App() {
  const [count, setCount] = useState(0);
  const intervalId = useRef(null);
  console.log(`๋ Œ๋”๋ง  ... count: ${count}`);

  const startCounter = () => {
    intervalId.current = setInterval(() => setCount((count) => count+1), 1000);
    console.log(`์‹œ์ž‘... intervalId: ${intervalId.current}`);
  }

  const stopCounter = () => {
    clearInterval(intervalId.current);
    console.log(`์ •์ง€... intervalId: ${intervalId.current}`);
  }

  return (
    <div>
      <p>์ž๋™ ์นด์šดํŠธ: {count}</p>
      <button onClick={startCounter}>์‹œ์ž‘</button>
      <button onClick={stopCounter}>์ •์ง€</button>
    </div>
  );
}

export default App;

 

intervalId๋ฅผ useRef๋กœ ์ •์˜ํ•œ ๋’ค startCounter ๋ถ€๋ถ„์—์„œ intervalId.current์— setIntervalํ•จ์ˆ˜๋ฅผ ๋„ฃ์œผ๋ฉด ์žฌ๋ Œ๋”๋ง์ด ๋˜์–ด๋„ ์ดˆ๊ธฐ์— ์ €์žฅํ•ด ๋‘์—ˆ๋˜ setInterval DOM API์˜ ๊ฐ’์„ ์œ ์ง€ํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋Š” stopCounterํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ๋„ ์ผ๊ด€์„ฑ์„ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์˜๋„ํ•˜๋Š” setInterval DOM API๋ฅผ ์ง€์šธ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

'React' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

State ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ  (0) 2022.05.07
React - ํ•ฉ์„ฑ  (0) 2022.05.07
React - useEffect, useCallback  (0) 2022.04.11