๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
ํ”„๋ก ํŠธ์—”๋“œ/React

useRef

by alswlfl 2022. 11. 16.

useRef

useRef๋กœ ํŠน์ • DOM ์„ ํƒํ•˜๊ธฐ

โ˜… DOM(๋ฌธ์„œ ๊ฐ์ฒด ๋ชจ๋ธ): XML์ด๋‚˜ HTML๋ฌธ์„œ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์ผ์ข…์˜ ์ธํ„ฐํŽ˜์ด์Šค, ์ด ๊ฐ์ฒด ๋ชจ๋ธ์€ ๋ฌธ์„œ ๋‚ด์˜ ๋ชจ๋“  ์š”์†Œ๋ฅผ ์ •์˜ํ•˜๊ณ , ๊ฐ๊ฐ์˜ ์š”์†Œ์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ• ์ œ๊ณต

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ํŠน์ • DOM์„ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์— getElementById, querySelector ๊ฐ™์€ DOM. Selector ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ DOM ์„ ํƒ
  • ๋ฆฌ์•กํŠธ์—์„œ๋Š” ref์‚ฌ์šฉ
  1. ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ: useRef๋ผ๋Š” Hook ํ•จ์ˆ˜ ์‚ฌ์šฉ
  2. ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ: ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ React.createRef๋ผ๋Š” ํ•จ์ˆ˜ ์‚ฌ์šฉ

useRef์‚ฌ์šฉ ์ด์œ 

  • ๊ฐ’ ์ €์žฅ: ํ˜„์žฌ ์ €์žฅํ•˜๊ณ  ์‹ถ์€ ๊ฐ’์„ ๋ฆฌ๋ Œ๋”๋ง ์—†์ด ์ €์žฅ
  • DOM ์ฐธ์กฐ: DOM์ฐธ์กฐ๊ฐ€๋Šฅ, ํ˜„์žฌ DOM์—์„œ element์˜ scroll์œ„์น˜, image์˜ size ๋“ฑ์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • useState๋กœ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋˜๋ฉด, ๋ฆฌ๋ Œ๋”๋ง์ด ๊ณ„์† ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ๋น„ํšจ์œจ์ ์ด๊ณ , ์ฝ”๋“œ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง
import React, { useState, useRef } from "react";

function InputSample() {
  const [inputs, setInputs] = useState({
    name: "",
    nickname: "",
  });
  const nameInput = useRef();

  const { name, nickname } = inputs;//๋น„๊ตฌ์กฐํ™” ํ• ๋‹น์„ ํ†ตํ•ด ๊ฐ’ ์ถ”์ถœconst onChange = (e) => {
    const { value, name } = e.target;//์šฐ์„  e.target์—์„œ name๊ณผ value๋ฅผ ์ถ”์ถœ
    setInputs({
      ...inputs,//๊ธฐ์กด์˜ input๊ฐ์ฒด ๋ณต์‚ฌํ•œ ๋’ค
      [name]: value,//nameํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ฐ’์„ value๋กœ ์„ค์ •
    });
  };
  const onReset = () => {
    setInputs({
      name: "",
      nickname: "",
    });
    nameInput.current.focus();//onResetํ•จ์ˆ˜์—์„œ input์— ํฌ์ปค์Šคํ•˜๋Š” focus() DOM API
  };
  return (
    <div>
      <input
        name="name"
        placeholder="์ด๋ฆ„"
        onChange={onChange}
        value={name}
        ref={nameInput}
      />
      <input
        name="nickname"
        placeholder="๋‹‰๋„ค์ž„"
        onChange={onChange}
        value={nickname}
      />
      <button onClick={onReset}>์ดˆ๊ธฐํ™”</button>
      <div>
        <b>๊ฐ’:</b>
        {name} ({nickname})
      </div>
    </div>
  );
}

export default InputSample;
  • useRef()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Ref ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ , ์ด ๊ฐ์ฒด๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์„ ํƒํ•˜๊ณ  ์‹ถ์€ DOM์— ref๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•จ
  • Ref๊ฐ์ฒด์˜ .current๊ฐ’์€ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” DOM ์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋จ

๋ฐฐ์—ด ๋ Œ๋”๋ง

import React from "react";

function User({ user }) {
  return (
    <div>
      <b>{user.username}</b> <span>({user.email})</span>
    </div>
  );
}

function UserList() {
  const users = [
    { id: 1, username: "velopert", email: "public.velopert@gmail.com" },
    { id: 2, username: "tester", email: "tester@example.com" },
    { id: 3, username: "liz", email: "liz@example.com" },
  ];
  return (
    <div>
      <User user={users[0]} />
      <User user={users[1]} />
      <User user={users[2]} />
    </div>
  );
}

export default UserList;
  • ๋ฐฐ์—ด์ด ๊ณ ์ •์ ์ด๋ฉด ๊ดœ์ฐฎ์ง€๋งŒ, ๋ฐฐ์—ด ์ธ๋ฑ์Šค ํ•˜๋‚˜ํ•˜๋‚˜ ์กฐํšŒํ•˜๋ฉฐ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋™์ ์ธ ๋ฐฐ์—ด ๋ Œ๋”๋ง ๋ชปํ•จ

๋™์ ์ธ ๋ฐฐ์—ด ๋ Œ๋”๋ง ๋ฐฉ๋ฒ•

: ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐฐ์—ด์˜ ๋‚ด์žฅํ•จ์ˆ˜ map() ์‚ฌ์šฉ, ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ฐ˜ ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด์„ ๋ฆฌ์•กํŠธ ์—˜๋ฆฌ๋จผํŠธ๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜

โญ๏ธ map: ๋ฐฐ์—ด ์•ˆ์˜ ๊ฐ ์›์†Œ๋ฅผ ๋ณ€ํ™˜ํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉ

  • ๋ฆฌ์•กํŠธ์—์„œ ๋ฐฐ์—ด ๋ Œ๋”๋ง ํ•  ๋•Œ, key๋ผ๋Š” props ์„ค์ •ํ•ด์•ผํ•จ

โ–บkey ๊ฐ’์€ ๊ฐ ์›์†Œ๋“ค๋งˆ๋‹ค ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ณ ์œ ๊ฐ’์œผ๋กœ ์„ค์ •

import React from "react";

function User({ user }) {
  return (
    <div>
      <b>{user.username}</b> <span>({user.email})</span>
    </div>
  );
}

function UserList() {
  const users = [
    { id: 1, username: "velopert", email: "public.velopert@gmail.com" },
    { id: 2, username: "tester", email: "tester@example.com" },
    { id: 3, username: "liz", email: "liz@example.com" },
  ];
  return (
    <div>
      {users.map((user) => (
        <User user={user} key={user.id} />
      ))}
    </div>
  );
}

export default UserList;
  • ๋ฐฐ์—ด์„ ๋ Œ๋”๋ง ํ•  ๋•Œ key ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฐฐ์—ด์˜ index๊ฐ’์„ key๋กœ ์‚ฌ์šฉํ•˜๊ณ , ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ๋œธ

โ€ป ๋ฐฐ์—ด ์•ˆ์˜ ์›์†Œ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ณ ์œ ํ•œ ๊ฐ’์ด ์—†๋‹ค๋ฉด map()ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์„ค์ •ํ•˜๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜์˜ ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ index๋ฅผ key๋กœ ์‚ฌ์šฉ

 return (
    <div>
      {users.map((user, index) => (
        <User user={user} key={index} />
      ))}
    </div>
  );

key์˜ ์กด์žฌ์œ ๋ฌด์— ๋”ฐ๋ฅธ ์—…๋ฐ์ดํŠธ ๋ฐฉ์‹

key๊ฐ€ ์—†์„ ๋•Œ,

const array=['a','b','c','d'];

array.map(item=><div>{item}</div>);

Q. b์™€ c ์‚ฌ์ด์— z๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒฝ์šฐ

A. ๋ฆฌ๋ Œ๋”๋ง ์‹œ,  <div>b</div>์™€ <div>c</div>์‚ฌ์ด์— ์ƒˆ๋กœ์šด divํƒœ๊ทธ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ธฐ์กด์˜ c๊ฐ€ z๋กœ ๋ฐ”๋€Œ๊ณ ,  d๋Š” c๋กœ ๋ฐ”๋€Œ๊ณ , ๋งจ ๋งˆ์ง€๋ง‰์— d๊ฐ€ ์ƒˆ๋กœ ์‚ฝ์ž…

Q. a๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒฝ์šฐ

A. ๊ธฐ์กด์˜ a๊ฐ€ b๋กœ ๋ฐ”๋€Œ๊ณ , b๋Š” z๋กœ ๋ฐ”๋€Œ๊ณ , z๋Š” c๋กœ ๋ฐ”๋€Œ๊ณ , c๋Š” d๋กœ ๋ฐ”๋€Œ๊ณ , ๋งจ ๋งˆ์ง€๋ง‰์— ์žˆ๋Š” d์ œ๊ฑฐ

์ฆ‰, key๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ, ๊ธฐ์กด์— ์žˆ๋˜ ๊ฐ’์„ ๊ฑด๋“ค์ด๋ฉด์„œ ์—…๋ฐ์ดํŠธ

 

key๊ฐ€ ์žˆ์„ ๋•Œ,

[
  {
    id: 0,
    text: 'a'
  },
  {
    id: 1,
    text: 'b'
  },
  {
    id: 2,
    text: 'c'
  },
  {
    id: 3,
    text: 'd'
  }
];

array.map(item => <div key={item.id}>{item.text}</div>);

key๊ฐ€ ์žˆ์„ ๋•Œ, ์ˆ˜์ •๋˜์ง€ ์•Š๋Š” ๊ธฐ์กด์˜ ๊ฐ’์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์›ํ•˜๋Š” ๊ณณ์— ๋‚ด์šฉ์„ ์‚ฝ์ž…ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œ

  • ๋ฐฐ์—ด ์•ˆ์— ์ค‘๋ณต๋˜๋Š” key๊ฐ€ ์žˆ์„ ๋•Œ, ๋ Œ๋”๋ง ์‹œ ์˜ค๋ฅ˜๋ฉ”์‹œ์ง€๊ฐ€ ์ฝ˜์†”์— ๋‚˜ํƒ€๋‚˜ ์—…๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๋Œ€๋กœ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์Œ

useRef๋กœ ์ปดํฌ๋„ŒํŠธ ์•ˆ์˜ ๋ณ€์ˆ˜ ๋งŒ๋“ค๊ธฐ

useRef์˜ ์šฉ๋„

  1. DOM ์„ ํƒ
  2. ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์กฐํšŒ ๋ฐ ์ˆ˜์ • ํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜ ๊ด€๋ฆฌ
  • setTimeout, setInterval์„ ํ†ตํ•ด์„œ ๋งŒ๋“ค์–ด์ง„ id
  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค
  • scroll์œ„์น˜ โ–ธ [react] scroll event (ํ…Œ์ŠคํŠธ)
import React from "react";

function User({ user }) {
  return (
    <div>
      <b>{user.username}</b> <span>({user.email})</span>
    </div>
  );
}

function UserList({ users }) {
  return (
    <div>
      {users.map((user) => (
        <User user={user} key={user.id} />
      ))}
    </div>
  );
}

export default UserList;
import React, { useRef } from "react";
import UserList from "./UserList";

function App() {
  const users = [
    {
      id: 1,
      username: "velopert",
      email: "public.velopert@gmail.com",
    },
    {
      id: 2,
      username: "tester",
      email: "tester@example.com",
    },
    {
      id: 3,
      username: "liz",
      email: "liz@example.com",
    },
  ];

  const nextId = useRef(4); //useRef() ์‚ฌ์šฉํ•  ๋•Œ ํŒŒ๋ผ๋ฏธํ„ฐ ๋„ฃ์–ด์ฃผ๋ฉด, ์ด ๊ฐ’์ด .current๊ฐ’์˜ ๊ธฐ๋ณธ๊ฐ’์ด ๋จ
  const onCreate = () => {
    nextId.current += 1; //๊ฐ’ ์ˆ˜์ • ์‹œ, .current ๊ฐ’ ์ˆ˜์ •ํ•˜๋ฉด ๋˜๊ณ , ์กฐํšŒํ•  ๋•Œ๋„ .current์กฐํšŒํ•˜๋ฉด ๋จ
  };
  return <UserList users={users} />;
}

export default App;