React - useRef

Leo·2021년 4월 23일
0

React

목록 보기
2/5
post-thumbnail

useRef

JavaScript에서 특정 DOM을 선택해야할 경우에는 일반적으로 getElementByIdquerySelector와 같은 DOM Selector 함수를 사용한다. 이와 같은 동작을 리액트에서는 ref를 사용해서 구현한다. 함수형 컴포넌트에서 ref를 사용할 때는 useRef 라는 Hook 함수를 사용하고 클래스형 컴포넌트에서는 콜백함수를 사용하거나 React.createRef라는 함수를 사용한다.

useRef로 특정 DOM 요소 선택하기

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

const InputSample = () => {
  const [inputs, setInputs] = useState({
    name: "",
    nickname: "",
  });
  const nameInput = useRef();	// useRef()를 사용해서 Ref 객체 생성

  const { name, nickname } = inputs;

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

  const onReset = () => {
    setInputs({
      name: "",
      nickname: "",
    });
    nameInput.current.focus();	// nameInput.current가 특정 DOM을 가리킴.ㄴ
  };

  return (
    <div>
      <input
        name="name"
        value={name}
        placeholder="이름"
        onChange={onChange}
        ref={nameInput}	// 특정 DOM에 ref를 지정
      />
      <input
        name="nickname"
        value={nickname}
        placeholder="닉네임"
        onChange={onChange}
      />
      <button onClick={onReset}>초기화</button>
      <div>
        <b>: </b>
        {name} {nickname}
      </div>
    </div>
  );
};

export default InputSample;

useRef로 컴포넌트 안의 변수 만들기

useRef는 DOM을 선택하는 용도 외에 컴포넌트 내부에서 조회 및 수정할 수 있는 변수를 관리하는데도 사용된다. useRef로 관리하는 변수는 값이 변경된다고 해도 컴포넌트가 리렌더링되지 않는다. 즉, 리액트 컴포넌트에서의 상태는 상태를 변경하는 함수를 호출하고나서 렌더링된 다음에 업데이트된 상태를 조회할 수 있지만 useRef로 관리하고 있는 변수는 설정 후에 바로 조회할 수 있다.

// App.js
import React, { useState, useRef } from "react";
import CreactUser from "./components/CreateUser";
import UserList from "./components/UserList";

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: "Leo",
      email: "jang.xmin@gmail.com",
    },
    {
      id: 2,
      username: "Ryan",
      email: "Ryan@kakao.com",
    },
    {
      id: 3,
      username: "Con",
      email: "Con77@naver.com",
    },
  ]);

  const nextId = useRef(4);	// useRef를 변수로 사용

  const onCreate = () => {
    // 배열에 항목 추가
    const user = {
      id: nextId.current,
      username,
      email,
    };
    
    // 불변성을 유지하기 위해서 spread 문법을 사용하거나 concat을 사용
    setUsers([...users, user]); 	// spread
    // setUsers(users.concat(user));	// concat

    setInputs({
      username: "",
      email: "",
    });
    nextId.current += 1;
  };

  return (
    <div className="App">
      <CreactUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} />
    </div>
  );
}

export default App;
// CreateUser.js
import React from "react";

const CreactUser = ({ username, email, onChange, onCreate }) => {
  return (
    <div>
      <input
        name="username"
        placeholder="계정명"
        onChange={onChange}
        value={username}
      />
      <input
        name="email"
        placeholder="이메일"
        onChange={onChange}
        value={email}
      />
      <button onClick={onCreate}>등록</button>
    </div>
  );
};

export default CreactUser;

왜 useRef를 사용해서 변수를 만드는건가?

let을 사용해서 변수를 선언하지 않고 굳이 useRef를 사용하는 점이 단번에 이해가 가지 않지만 useRef를 사용하면 렌더링될 때마다 해당 값이 초기화되는 것을 피할 수 있다고 한다. 다시말해 렌더링할 요소들을 최대한 줄임으로써 성능적으로 이점을 가질 수 있다는 것이다.

참조

0개의 댓글