useRef 함수는 리액트의 함수형 컴포넌트에서 사용하는 Hook의 한 종류로, 기본적으로 두 가지 기능을 가지고 있다.
1. 특정 DOM을 선택하여 저장
2. state와 관련없는 변수 저장
1. 특정 DOM을 선택하여 저장
특정 DOM 선택 기능은 보통 어떤 DOM element를 선택해 해당 element의 스크롤, 사이즈, 온 포커스 기능 등을 구현하기 위해 사용된다.
import React, { useState, useRef } from "react";
function InputSample() {
const [inputs, setInputs] = useState({ name: '', nickname: '' });
const nameInput = useRef(); // input element를 담기 위한 객체
const { name, nickname } = inputs;
const onChange = e => {
const { value, name } = e.target;
setInputs({ ...inputs, [name]: value })
}
const onReset = () => {
setInputs({ name: '', nickname: '', })
nameInput.current.focus(); // 리셋시 input element를 focus 하도록 구현
}
return (
<div>
{/* input에 ref={nameInput}을 통해 nameInput 변수가 input element를 가리키도록 구현 */}
<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;
위 코드를 실행하고 초기화 버튼을 클릭하면, 사진과 같이 focus가 name을 입력하는 input에 올라간 것을 확인할 수 있다.
2. state와 관련없는 변수 저장
사실 이 부분이 더 중요한 부분이라고 생각되는데, useRef를 사용하면 state에 상관없는 (값을 변화시켜도 다시 렌더링 되지 않고, 다시 렌더링 되어도 해당 값이 변하지 않는) 변수를 선언할 수 있다.
import React, { useRef, useState } from 'react';
function App() {
const [stateCounter, setStateCounter] = useState(0);
const refCounter = useRef(0);
const increaseStateCounter = () => {
setStateCounter(prev => prev + 1);
console.log('stateCounter 증가!', stateCounter);
}
const increaseRefCounter = () => {
refCounter.current += 1;
console.log('refCounter 증가!', refCounter.current);
}
return (
<>
{console.log('re-render!')}
{console.log('re-render!')}
<div>
stateCounter: <b>{stateCounter}</b>
</div>
<button onClick={increaseStateCounter}>stateCounter 증가</button>
<div>
<b>-----------------------</b>
</div>
<div>
refCounter: <b>{refCounter.current}</b>
</div>
<button onClick={increaseRefCounter}>refCounter 증가</button>
</>
);
}
'stateCounter 증가'를 3번 클릭한 결과, state값 증가에 따른 리렌더링이 3번 이루어졌다.
리렌더링이 매번 이루어지므로, DOM에 보이는 값 또한 매번 증가되었다.
반면, 'refCounter를 증가'를 3번 클릭할 경우 콘솔 창을 통해 refCounter 값이 증가된 것은 보이지만, 리렌더링이 이루어지지 않으므로 DOM 업데이트 또한 이루어지지 않는다. 대신, 새로고침을 하거나 stateCounter를 증가시켜 렌더링을 다시 시킨다면, 업데이트된 refCounter값이 올바르게 표시된다.
직접적인 let 변수나, 객체를 선언해서 컴포넌트 내부 변수를 사용하는 것이 아니고 useRef를 사용하는 이유는, 직접적인 내부 변수를 선언할 경우 리렌더링 시에 변수 값이 초기화되기 때문이다. 반면, useRef의 경우 일반적인 자바스크립트 객체로서 메모리 heap에 저장되므로, 항상 같은 메모리 주소를 참조하여 컴포넌트가 아무리 리렌더링 되더라도 이미 저장된 값 자체는 삭제되지 않고 전역변수처럼 남아있게 된다.
'Library & Framework > React.js' 카테고리의 다른 글
[React.js] create-react-app vulnerabilities / CRA 버전 취약 오류 (1) | 2021.11.12 |
---|---|
[React.js] 리액트 useEffect 기본 사용 (0) | 2021.10.14 |
[React.js] 리액트 JSX (0) | 2021.10.12 |
[React.js] 리액트에 파이어베이스 연동하기 / React + Firebase (0) | 2021.04.12 |
[React.js] 리액트 이미지 사용 / react img src (2) | 2021.02.28 |