react

[react] useRef()

beaksul 2022. 12. 7. 21:01

1. useRef()

 

 

공식문서 속 useRef의 정의

useRef는 .current프로퍼티로 전달된 인자(initialValue)로 초기화된 변경 가능한 ref객체를 반환합니다.

반환된 객체는 컴포넌트의 전 생애주기를 통해 유지될 것입니다.

본질적으로 useRef는 .current프로퍼티에 변경 가능한 값을 담고 있는 상자와 같습니다.

 

useRef가 사용되는 경우

  • 특정 DOM 선택
  • 컴포넌트 안의 변수 생성
  • 리랜더링 방지

 

 

2. 특정 DOM 선택하기

 

 

useRef()를 사용하여 Ref객체를 만들고, 이 객체를 선택하고 싶은 DOM에 ref값으로 설정한다.

그러면, Ref객체의 .current값은 DOM 을 가리키게 된다.

 

초기화 버튼을 클릭하면 이름 input에 포커스가 되는 onReset 함수

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

function InputSample() {
  const nameInput = useRef();

  const onReset = () => {
    setInputs({
      name: '',
      nickname: '',
    });
    nameInput.current.focus();
  };
  
  const onChange = e => {
    const { value, name } = e.target;

    setInputs({
      ...inputs,
      [name]: value,
    });
  };

  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;

 

2초뒤에 input에 포커스

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

function App() {
  const inputFocus = useRef();
  // querySelector와 비슷하다. 엘리먼트를 선택
  setTimeout(() => {
    inputFocus.current.focus();
  }, 2000);
  return (
    <div className="App">
      <input ref={inputFocus}></input>
    </div>
  );
}

export default App;

 

 

3. 컴포넌트 안의 변수 만들기

 


useRef()를 사용할 때 파라미터를 넣어주면, 이 값이 .current값의 기본값이 된다.

그리고 이 값을 수정할 때는 .current값을 수정하면 되고 조회할 때는 .current를 조회하면 된다.

 

현재 id가 3까지 지정있으므로 앞으로 생성될 nextId의 초기값을 4로 설정하고 onCreate함수에 사용

const nextId = useRef(4);

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 onCreate = () => {
  const user = {
    id: nextId.current,
    username,
    email,
  }
};

 

 

4. 리렌더링 방지하기

 

 

onChange구현 부분을 ref값으로 대체해서 매번 리렌더링 되는 단점을 해결할 수 있다. 

state로 event의 value에 접근하지 않고 refObject.current.value를 사용하는 방법이다.

 

수정 전 코드

const onChange = e => {
  const { value, name } = e.target;
  
  setInputs({
    ...inputs,
    [name]: value,
  });
};

const onCreate = () => {
  const user = {
    id: nextId.current,
    username,
    email,
  };

  setUsers(users.concat(user));

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

  nextId.current += 1;
};
<div>
  <input
  name="username"
  placeholder="계정명"
  onChange={onChange}
  value={username}
  />
  <input
  name="email"
  placeholder="이메일"
  onChange={onChange}
  value={email}
  />
  <button onClick={onCreate}>등록</button>
</div>

 

refObject.current.value를 이용해 수정한  코드

input의 onChange를 ref로 대체

const usernameRef = useRef('');
const emailRef = useRef('');

const onCreate = () => {
  const user = {
    id: nextId.current,
    username: usernameRef.current.value,
    email: emailRef.current.value,
  };

  setUsers(users.concat(user));
  
  setInputs({
    username: '',
    email: '',
  });
  
  nextId.current += 1;
};
<div>
  <input name="username" placeholder="계정명" ref={usernameRef} />
  <input name="email" placeholder="이메일" ref={emailRef} />
  <button onClick={onCreate}>등록</button>
</div>