[ React ] useRef로 컴포넌트 안에 변수 만들기

ma.caron_g·2022년 12월 8일
0

React

목록 보기
7/8
post-thumbnail

<출처>

[ ref / UseRef ]

컴포넌트에서 특정 DOM을 사용 지정해 사용할 때 ref를 사용합니다.
그리고 함수형 컴포넌트에서 이를 설정할 때, useRef를 사용합니다.

useRef Hook은 DOM을 선택하는 용도 외에도 다른 용도가 있는데, 이는 컴포넌트 안에서 조회 및 수정을 할 수 있는 변수를 관리하는 것입니다.

useRef로 관리하는 변수는 값이 바뀐다고 컴포넌트가 재렌더링 되지 않습니다.

리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고나서 그 다음 렌더링 이후로 업데이트 된 상태를 조회할 수 있는 반면, useRef로 관리하고 있는 변수는 설정 후 바로 조회할 수 있습니다.

다음과 같은 값을 관리할 수 있습니다.

  • setTimeout, setInterval을 통해서 만들어진 id
  • 외부 라이브러리를 사용하여 생성된 인스턴스
  • Scroll 위치

이 글에서는 App 컴포넌트에서 useRef를 사용하여 변수를 관리해보겠습니다.

useRef를 사용하여 변수를 관리하기 전에 해야 할 작업이 있습니다.

지금은 우리가 UserList 컴포넌트 내부에서 배열을 직접 선언해서 사용을 하고 있는데, 이렇게 UserList에서 선언해서 사용하는 대신, 이 배열을 App에서 선언하고 UserList에게 props로 전달해주겠습니다.

[ Ref ]

기존 HTML 문서 작성에서 자바스크립트로 해당 객체를 연결하려면 태그 안에 id값을 주거나 class 값을 주어

  • document.getElementById('id');
  • document.querySelector('#class');
    를 사용하여 해당 객체를 변수와 연결했다면,

리액트는 태그 안에 ref값을 지정하여 해당 ref값을 사용하여 해당 객체를 지정할 수 있습니다.

// HTML Document
<input ref={ImNameInput}`\>
// Javascript
ImNameInput.current.focus();

여기서 current는 우리가 사용하고자하는 DOM을 나타냅니다.

다음과 유사합니다

console.log(e);
// 이벤트 발생 객체 태그 출력
// input 출력
console.log(ImNameInput);
// 이벤트 발생 객체 태그 출력
// input 출력.


console.log(e.target);
// 이벤트 발생 객체 지정 출력
// input name='name' value='aaa' ...
console.log(ImNameInput.current);
// input name='name' value='aaa' ...

그럼, 다음과 같이

[ UserList.js ]

import React from "react";
import './App.css'

function User( {user, onRemove } ) {
    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;

[ App.js ]

import './App.css';
import React, {useRef, useState} from 'react';
import UserList from './UserList';
import CreateUser from './CreateUser';
import InputSample from './InputSample';
function App() {

  const [inputs, setInputs] = useState ({
    username: '',
    email: ''
  })
  const {username, email} = inputs;
  const onChange = (e) => {
    const {name, value} = e.target;
    setInputs( {
      ...inputs,
      \[name]: value
    });
  }
  const [users, setUsers] = useState ([
    {
      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);
  const onCreate = ()=> {
    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers([...users, user]);

    setInputs({
      username: '',
      email: ''
    })
  }

  return (
    <div className='container'>
      <div className='basic'>
        <CreateUser
        username={username}
        email={email} 
        onChange={onChange} 
        onCreate={onCreate}/>
        </div>
      <div className='usrlist'>
        <UserList users={users} />
      </div>
    </div>
  )

}


export default App;

다음과 같이 코드를 작성하면

위와 같은 모습으로 출력이 됩니다.
(css를 건드린 상태입니다.)

App.js 코드에서 이미 배열에 3가지의 목록이 들어가있고, 각 컴포넌트의 key값을 id값으로 물려주었기 때문에 nextId를 useRef를 이용하여 id의 시작값을 4로 주었습니다.

const [변수명] = useRef(Value)

Value(파라미터)값을 current의 값으로 지정.

현재 nextId를 변수명으로 지었는데

이를 console.log(nextId)로 출력하면

// 등록 클릭
current:{5} (현재 id에서 +1한 값)
// 등록 클릭
current:{6} (현재 id에서 +1한 값)

이를 comsole.log(nextId.current)한다면

// 등록 클릭
5
// 등록 클릭
6

위와 같이 출력되게 됩니다. 자동으로 id값이 1이 증가하여 적용됩니다.

Ref를 사용하는 경우는 다음과 같습니다.

  • 포커스, 텍스트 선택영역 혹은 미디어의 재생을 관리할 때
  • 애니메이션을 직접적으로 실행시킬 때
  • 서드 파티 DOM 라이브러리를 React와 같이 사용할 때

**선언적으로 해결할 수 있는 문제는 ref 사용을 지양**
profile
다른 사람이 만든 것을 소비하는 활동보다, 내가 생산적인 활동을 하는 시간이 더 많도록 생활화 하자.

0개의 댓글