useRef 첫 번째 기능: Component의 Dom 취득하기
시험해볼 소스코드는 다음과 같습니다.
import React, { useState, useRef } from 'react';
function InputSample() {
const [inputs, setInputs] = useState({name: ''});
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: ''});
nameInput.current.focus();
};
return (
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput}
/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
{name} ({nickname})
</div>
</div>
);
}
export default InputSample;
useRef에 정말 컴포넌트의 Dom이 들어와있는지 아닌지를 확인하기 위한 목적의 어플입니다. 상단부에서 useRef를 선언하고, 컴포넌트에 useRef에 의해 생성된 인스턴스를 붙여줍니다. ref={nameInput}
와 같이 컴포넌트에 ref={인스턴스}
의 방법으로 useRef를 컴포넌트에 부착시킬 수 있습니다.
어플의 요건은 단순합니다. 하나의 input이 있고, reset버튼을 누르면 아래와 같이 작동합니다.
input
state가 초기화되고, 컴포넌트가 re-renderinput
에 포커싱


위의 그림처럼 초기화버튼을 클릭하자 input에 focusing이 된 것을 볼 수 있습니다.(포커싱 되면 까만 테두리로 표현돼요)

ref.current
에 정말 dom
이 들어와있는지, 개발자 도구로 확인해봅시다. input의 dom이 잘 들어와 있네요. 따라서 ref.current
를 제어해서 dom 내부 함수를 사용할 수 도 있고, Dom내부의 값을 빼올 수 도 있습니다.
useRef 두 번째 기능: re-render시에도 격납한 값이 불변
import React, { useState, useRef } from "react"
function ManualCounter() {
const [count, setCount] = useState(0)
const intervalId = useRef(null)
console.log(`랜더링... count: ${count}`)
const startCounter = () => {
intervalId.current = setInterval(() => setCount((count) => count + 1), 1000)
console.log(`시작... intervalId: ${intervalId.current}`)
}
const stopCounter = () => {
clearInterval(intervalId.current)
console.log(`정지... intervalId: ${intervalId.current}`)
}
return (
<>
<p>자동 카운트: {count}</p>
<button onClick={startCounter}>시작</button>
<button onClick={stopCounter}>정지</button>
</>
)
}
위 어플의 전제적인 흐름은 다음과 같습니다.
- 시작 버튼 클릭
- 1초에 한번씩
count
state를 업데이트 - state가 업데이트 될 때마다
ManualCounter
컴포넌트 re-rendering
(위의 과정 반복..)
위의 어플을 기동시키면 다음과 같은 console을 얻을 수 있습니다.
시작... intervalId: 4
랜더링... count: 1
랜더링... count: 2
랜더링... count: 3
랜더링... count: 4
정지... intervalId: 4
시작... intervalId: 5
랜더링... count: 5
랜더링... count: 6
랜더링... count: 7
랜더링... count: 8
정지... intervalId: 5
콘솔에서 시작할 때의 intervalId
와 정지할 때의 intervalId
가 동일한 것을 알 수 있습니다. 시작시 intervalId.current
에 격납해 두었던 intervalId
가 컴포넌트가 여러번 re-render된 뒤에도 값이 초기화되지 않고 intervalId.current
에 저장되어 있었음을 의미하죠.
'frameworks > react' 카테고리의 다른 글
React.memo() 현명하게 사용하기, 언제 사용해야할까, 언제 사용하면 안될까 (0) | 2022.01.28 |
---|---|
Publisher subscriber pattern(포스트 하단에 코드가 움직이는 순서 정리) (0) | 2021.05.18 |
React Hooks Update Dictionary State: (...) operators의 활용 (0) | 2021.02.26 |
벨로퍼트와 함께하는 모던 리액트 강의(https://react.vlpt.us/) (0) | 2021.02.18 |
footer 하단 고정 (간단!) (0) | 2020.09.22 |