240818 React useRef

์‹ ํ•œ๋ณ„ยท2024๋…„ 8์›” 17์ผ

๐Ÿ’ช ๋งค์ผ ๊ธฐ๋ก

๋ชฉ๋ก ๋ณด๊ธฐ
56/97

01. useRef๋ž€?

๐Ÿ“š ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜ ( useState ๋ž‘ ๋น„์Šท? )

(1) useRef hook ์†Œ๊ฐœ

Re-rendering๊ณผ ์ƒ๊ด€์—†์ด ๊ฐ’์„ ๊ธฐ์–ตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ
๐Ÿ’จ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ DOM API๋ฅผ ์ง์ ‘์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  DOM ์š”์†Œ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ ์ž์ฃผ ์‚ฌ์šฉ

(2) ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

import "./App.css";
import { useRef } from "react";

function App() {
  const ref = useRef("์ดˆ๊ธฐ๊ฐ’");
  console.log("ref", ref);

  return (
    <div>
      <p>useRef์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ์—์š”.</p>
    </div>
  );
}

export default App;

๋ณ€๊ฒฝ๋„ ๊ฐ€๋Šฅ

import "./App.css";
import { useRef } from "react";

function App() {
  const ref = useRef("์ดˆ๊ธฐ๊ฐ’");
  console.log("ref 1", ref);

  ref.current = "๋ฐ”๊พผ ๊ฐ’";
  console.log("ref 1", ref);

  return (
    <div>
      <p>useRef์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ์—์š”.</p>
    </div>
  );
}

export default App;

๐Ÿ’ก ์ด๋ ‡๊ฒŒ ์„ค์ •๋œ ref ๊ฐ’์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ณ„์†ํ•ด์„œ ๋ Œ๋”๋ง ๋˜์–ด๋„ unmount ์ „๊นŒ์ง€ ๊ฐ’์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค! (์ค‘์š”)

์ด๋Ÿฌํ•œ ํŠน์ง•๋“ค ๋•Œ๋ฌธ์— useRef๋Š” ๋‹ค์Œ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

  1. ์ €์žฅ๊ณต๊ฐ„
    state์™€ ๋น„์Šทํ•œ ์—ญํ• ์„ ํ•˜์ง€๋งŒ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ๋žœ๋”๋ง์ด ์ผ์–ด๋‚˜๋Š” state์™€ ๋‹ฌ๋ฆฌ, ref ์ €์žฅํ•œ ๊ฐ’์€ ๋žœ๋”๋ง์„ ์ผ์œผํ‚ค์ง€ ์•Š์Œ => ref์˜ ๊ฐ’์ด ๋ณ€ํ•ด๋„ ๋‚ด๋ถ€ ๋ณ€์ˆ˜๋“ค์ด์ดˆ๊ธฐํ™” ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰!!
state๋Š” ๋ฆฌ๋ Œ๋”๋ง์ด ๊ผญ ํ•„์š”ํ•œ ๊ฐ’์„ ๋‹ค๋ฃฐ ๋•Œ ์“ฐ๋ฉด ๋œ๋‹ค.
ref๋Š” ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š” ๊ฐ’์„ ์ €์žฅํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

  1. DOM
    ๋ Œ๋”๋ง ๋˜์ž๋งˆ์ž ํŠน์ • input์ด focusing ๋ผ์•ผ ํ•˜๋Š” ๋“ฑ, DOM ์š”์†Œ๋ฅผ ํ•ธ๋“ค๋งํ•ด์•ผ ํ•˜๋Š” ์ˆœ๊ฐ„์ด๋ผ๋ฉด useRef๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์„ ํƒ์ง€

02. ์˜ˆ์ œ ์ฝ”๋“œ๋กœ ํŠน์ง• ์‚ดํŽด๋ณด๊ธฐ

(1) state vs ref

state๋Š” ๋ณ€๊ฒฝ๋˜๋ฉด ๋žœ๋”๋ง์ด ๋˜๊ณ , ref๋Š” ๋ณ€๊ฒฝ๋˜์–ด๋„ ๋ Œ๋”๋ง์ด ์•ˆ๋œ๋‹ค ๐Ÿ’จ

์•„๋ž˜ ์ฝ”๋“œ์—์„œ
plusStateCountButtonHandler ์™€ plusRefCountButtonHandler ๋Š” ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.

import "./App.css";
import { useRef, useState } from "react";

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

  const plusStateCountButtonHandler = () => {
    setCount(count + 1);
  };

  const plusRefCountButtonHandler = () => {
    countRef.current++;
  };

  return (
    <>
      <div>
        state ์˜์—ญ์ž…๋‹ˆ๋‹ค. {count} <br />
        <button onClick={plusStateCountButtonHandler}>state ์ฆ๊ฐ€</button>
      </div>
      <div>
        ref ์˜์—ญ์ž…๋‹ˆ๋‹ค. {countRef.current} <br />
        <button onClick={plusRefCountButtonHandler}>ref ์ฆ๊ฐ€</button>
      </div>
    </>
  );
}

export default App;

(2) DOM ์ ‘๊ทผ

<input /> ํƒœ๊ทธ์—๋Š” ref๋ผ๋Š” ์†์„ฑ์ด ์žˆ๋‹ค. ์ด๊ฑธ ํ†ตํ•ด ํ•ด๋‹น DOM ์š”์†Œ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค wow

  1. ์‚ฌ์šฉ ํ™”๋ฉด ๋งŒ๋“ค์–ด์ฃผ๊ธฐ (์•„์ด๋””/๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ๋ฐ›๊ธฐ)
import "./App.css";

function App() {
  return (
    <>
      <div>
        ์•„์ด๋”” : <input type="text" />
      </div>
      <div>
        ๋น„๋ฐ€๋ฒˆํ˜ธ : <input type="password" />
      </div>
    </>
  );
}

export default App;
  1. useRef ์‚ฌ์šฉํ•˜์—ฌ ํฌ์ปค์‹ฑ ์ฃผ๊ธฐ
import { useEffect, useRef } from "react";
import "./App.css";

function App() {
  const idRef = useRef("");

  // ๋ Œ๋”๋ง์ด ๋  ๋•Œ
  useEffect(() => {
    idRef.current.focus();
  }, []);

  return (
    <>
      <div>
        ์•„์ด๋”” : <input type="text" ref={idRef} />
      </div>
      <div>
        ๋น„๋ฐ€๋ฒˆํ˜ธ : <input type="password" />
      </div>
    </>
  );
}

export default App;

์•„์ด๋””๊ฐ€ 10์ž๋ฆฌ ์ž…๋ ฅ๋˜๋ฉด ์ž๋™์œผ๋กœ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„๋“œ๋กœ ์ด๋™ํ•˜๋Š” ์ฝ”๋“œ?!

import { useEffect, useRef, useState } from "react";
import "./App.css";

function App() {
  const idRef = useRef("");
  const pwRef = useRef("");

  const [id, setId] = useState("");

  const onIdChangeHandler = (event) => {
    setId(event.target.value);
  };

  // ๋ Œ๋”๋ง์ด ๋  ๋•Œ
  useEffect(() => {
    idRef.current.focus();
  }, []);

  // ์™œ useEffect ์•ˆ์— ๋†“์•˜์„๊นŒ์š”?
  useEffect(() => {
    if (id.length >= 10) {
      pwRef.current.focus();
    }
  }, [id]);

  return (
    <>
      <div>
        ์•„์ด๋”” :
        <input
          type="text"
          ref={idRef}
          value={id}
          onChange={onIdChangeHandler}
        />
      </div>
      <div>
        ๋น„๋ฐ€๋ฒˆํ˜ธ : <input type="password" ref={pwRef} />
      </div>
    </>
  );
}

export default App;

id.length โ‰ฅ 10 ์ด ๋กœ์ง์„ useEffect ์•ˆ์— ๋„ฃ์—ˆ๋Š”์ง€?
=> ๋ฐฐ์น˜ ์—…๋ฐ์ดํŠธ

0๊ฐœ์˜ ๋Œ“๊ธ€