React ์ฃผ๋ง #6

#6 ์นจ๋Œ€์—์„œ ๋’น๊ธ€

useRef ๋กœ ํŠน์ • DOM ์„ ํƒ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ํŠน์ • DOM์„ ์„ ํƒํ•ด์•ผํ•  ๋•Œ, getElementById, querySelector ๊ฐ™์€ DOM selector ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ ๊ฐ€๋”์‹ DOM์„ ์ง์ ‘ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
์ด ๋•Œ, ๋ฆฌ์•กํŠธ์—์„œ ref๋ผ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•œ๋‹ค.

ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ref ๋ฅผ ์‚ฌ์šฉ ํ•  ๋•Œ์—๋Š” useRef ๋ผ๋Š” Hook ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ React.createRef ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ํ˜„์žฌ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ „์— ๋งŒ๋“  InputSample ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ์ด๋ฆ„ input ์— ํฌ์ปค์Šค๊ฐ€ ์žกํžˆ๋„๋ก useRef ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ฒ ๋‹ค!

InputSample.js

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();
  };

  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 ์„ ๊ฐ€๋ฅดํ‚จ๋‹ค.

์œ„์˜ ์ฝ”๋“œ์—์„œ onReset ํ•จ์ˆ˜์—์„œ input์— ํฌ์ปค์Šค๋ฅผ ํ•˜๋Š” focus( ) API๋ฅผ ํ˜ธ์ถœํ•ด์คฌ๋‹ค.

nameInput.current.focus();

๊ฒฐ๊ณผ๋Š”...

์ดˆ๊ธฐํ™”๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ, ์ด๋ฆ„ input ํƒœ๊ทธ์— focus๊ฐ€ ๋“ค์–ด์˜จ๋‹ค.

๊ทธ๋ฆฌ๊ณ 

const refContainer = useRef(initialValue);

useRef๋Š” .current ํ”„๋กœํผํ‹ฐ๋กœ ์ „๋‹ฌ๋œ ์ธ์ž(initialValue)๋กœ ์ดˆ๊ธฐํ™”๋œ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ref ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ฐฐ์—ด ๋ Œ๋”๋งํ•˜๊ธฐ

์ด๋ฒˆ์—๋Š” ๋ฆฌ์•กํŠธ์—์„œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๋ฐฐ์—ด์„ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ฒ ๋‹ค.

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'
  }
];

์ด๋ ‡๊ฒŒ ๋ฐฐ์—ด์ด ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž!

์–ด๋–ป๊ฒŒํ•˜๋ฉด์€ ์ด ๋ฐฐ์—ด์„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์„๊นŒ?
๊ทธ๋ƒฅ ์ฝ”๋“œ ๊ทธ๋Œ€๋กœ ์ž‘์„ฑ์„ ํ•˜๋ฉด๋˜๋Š”๋ฐ, ์šฐ๋ฆฌ๋Š” src ํด๋”์— UserList๋ผ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

UserList.js

import React from 'react';

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>
      <div>
        <b>{users[0].username}</b> <span>({users[0].email})</span>
      </div>
      <div>
        <b>{users[1].username}</b> <span>({users[1].email})</span>
      </div>
      <div>
        <b>{users[2].username}</b> <span>({users[1].email})</span>
      </div>
    </div>
  );
}

export default UserList;

์œ„์—์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ดค๋Š”๋ฐ, ๋‹ค์‹œ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ผ์ผํžˆ ๋„ฃ๋Š”๊ฑด ๋น„ํšจ์œจ์ ์ด๋ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒˆ๋กœ ๋งŒ๋“ค์–ด๋ณด๊ฒ ๋‹ค.

UserList ํŒŒ์ผ์„ ๋‹ค์‹œ ์ˆ˜์ •ํ•ด์ฃผ๋ฉด...

์•„! ๊ทธ๋ฆฌ๊ณ  ํ•œ ํŒŒ์ผ์— ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ ์–ธํ•ด๋„ ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๋Š” ์—†๋‹ค!

UserList.js

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;

์ด์ œ ์ปดํฌ๋„ŒํŠธ๋ฅผ App ํŒŒ์ผ์—์„œ ๋ Œ๋”๋งํ•ด๋ณด๊ฒ ๋‹ค.

App.js

import React from 'react';
import UserList from './UserList';

function App() {
  return (
    <UserList />
  );
}

export default App;

๊ฒฐ๊ณผ๋Š”...

๋งŒ์•ฝ ๋ฐฐ์—ด์ด 100๊ฐœ ์ด์ƒ์ด๋ฉด ํ•˜๋‚˜ํ•˜๋‚˜ ์กฐํšŒํ•ด๊ฐ€๋ฉด์„œ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋น„ํšจ์œจ์ ์ด๋ผ ์ด๋Ÿด ๋•Œ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐฐ์—ด์˜ ๋‚ด์žฅํ•จ์ˆ˜์ธ map( )์„ ์‚ฌ์šฉํ•˜๋ฉด๋œ๋‹ค.

map() ํ•จ์ˆ˜๋Š” ๋ฐฐ์—ด์•ˆ์— ์žˆ๋Š” ๊ฐ ์š”์†Œ๋ฅผ ๋ณ€ํ™˜ํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋™์ ์ธ ๋ฐฐ์—ด์„ ๋ Œ๋”๋ง์„ ํ•  ๋•Œ๋Š” map ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ฐ˜ ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด์„ ๋ฆฌ์•กํŠธ ์—˜๋ฆฌ๋จผํŠธ๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.

UserList ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ด๋ณธ๋‹ค.

UserList.js

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} />
      ))}
    </div>
  );
}

export default UserList;

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๋ฉด ์ผ์ผํžˆ ๊ฐ ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ๋ฐ˜๋ณตํ•ด๊ฐ€๋ฉด์„œ ์“ฐ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ํ•œ ๋ฒˆ๋งŒ map ํ•จ์ˆ˜๋ฅผ ์“ฐ๋ฉด ๋ชจ๋“  ์š”์†Œ๊ฐ€ ๋ Œ๋”๋ง๋œ๋‹ค.

ํ•˜์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €์˜ ์ฝ˜์†”๋กœ ๊ฐ€๋ณด๋ฉด ํŠน์ • ์—๋Ÿฌ๊ฐ€ ๋ณด์ผ ๊ฒƒ ์ด๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋ฐฐ์—ด์„ ๋ Œ๋”๋งํ•  ๋•Œ, key๋ผ๋Š” props๋ฅผ ์„ค์ •ํ•ด์ค˜์•ผํ•œ๋‹ค.
key ๊ฐ’์€ ๊ฐ ์š”์†Œ๋“ค์˜ ๊ณ ์œ ๊ฐ’์„ ์„ค์ •ํ•ด์•ผ ํ•ด์„œ ์œ„์˜ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” id๊ฐ€ ๊ณ ์œ  ๊ฐ’์ด๋‹ค.

key prop์„ ์ถ”๊ฐ€ํ•˜๋ฉด...

UserList.js

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

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

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

์—ฌ๊ธฐ์„œ ์ •๋ฆฌํ•˜์ž๋ฉด...

map ํ•จ์ˆ˜์—์„œ key๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ๋Š”

  • Map์— key ๊ฐ’์ด์—†๋‹ค๋ฉด ์ค‘๊ฐ„์˜ ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ์„๋•Œ ๊ทธ ํ•˜์œ„ ๊ฐ’๋“ค์ด ์ „๋ถ€ ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ธ๋‹ค. key๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด key๋ฅผ ์ด์šฉํ•ด ์ค‘๊ฐ„์˜ ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๊ฒŒ ๋œ๋‹ค.

์ฐธ๊ณ  : ๋ฒจ๋กœํผํŠธ์™€ ํ•จ๊ป˜ํ•˜๋Š” ๋ชจ๋˜ ๋ฆฌ์•กํŠธ

๋А๋‚€์  :

  • ์˜ค๋Š˜์€ useRef์™€ ๋ฐฐ์—ด์„ ๋ Œ๋”๋ง์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์กŒ์Šต๋‹ˆ๋‹ค.
  • map ํ•จ์ˆ˜๋Š” ๋ฐฐ์—ด๋ฅผ ์ƒˆ๋กญ๊ฒŒ ๋ฆฌํ„ดํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ฆฌ์•กํŠธ์—์„œ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๊ณ , useRef๋Š” ์•„์ง ํ—ท๊ฐˆ๋ฆฌ๋Š” ๋ถ€๋ถ„์ด ์žˆ์„ ์ˆ˜ ์žˆ์–ด์„œ ๋‹ค์‹œ ๊ณต๋ถ€ํ•ด์•ผ๊ฒ ๋‹ค.

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ