useRef hook 은 mutable value(참조 또는 ref) 를 생성하고 DOM element에 접근하기위한 hook
Mutable value
useRef 는 초기값을 받고 참조(ref)를 리턴함
ref는 'current'라는 특수한 속성을 가진 객체임
import { useRef } from 'react';
function MyComponent() {
const initialValue = 0;
const reference = useRef(initialValue);
const someHandler = () => {
// ref의 value에 접근
const value = reference.current;
// ref의 value 수정
reference.current = newValue;
};
// ...
}
ref에 대해 두가지 규칙이 있음
1. ref의 value 는 component가 re-render 되어도 동일하게 유지됨
2. ref의 value를 수정하여도 re-reder 되지않음
use case1: 버튼 클릭에 대한 로깅
import { useRef, useState } from 'react';
function LogButtonClicks() {
const [countState, setCountState] = useState(0)
const handle = () => {
countRef.current++
// state 갱신시 re-render 발생
// setCountState(countState + 1)
console.log(`Clicked ${countRef.current} times`);
};
// render가 일어나는 경우에만 logging
console.log('I rendered!');
return <button onClick={handle}>Click me</button>;
}
- ref 와 state의 차이
- ref의 update는 re-render를 발생시키지 않지만, state는 re-render를 발생시킴
- ref의 update는 동기적(옳은 방식으로 썻을때), state는 비동기적임(state는 re-render이후 update됨)
- ref는 side effect에 대한 기반이되는 data를 저장하고, state는 화면에 직접 redering 될 정보를 저장
(와닿지 않음..)
use case1-1: timer, socket
import { useRef, useState, useEffect } from 'react';
function Stopwatch() {
const timerIdRef = useRef(0);
const [count, setCount] = useState(0);
const startHandler = () => {
if (timerIdRef.current) { return; }
timerIdRef.current = setInterval(() => setCount(c => c+1), 1000);
};
const stopHandler = () => {
clearInterval(timerIdRef.current);
timerIdRef.current = 0;
};
useEffect(() => {
return () => clearInterval(timerIdRef.current);
}, []);
return (
<div>
<div>Timer: {count}s</div>
<div>
<button onClick={startHandler}>Start</button>
<button onClick={stopHandler}>Stop</button>
</div>
</div>
);
}
1. start시 timer id가 ref에 저장됨
2. stop시 ref의 timer id 에 접근하여 해당 timer를 clear함
3. useEffect의 clean-up 함수에서도 clearInterval 을 하여 timer가 동작도중 unmount될시 timer를 clear하도록함
4. re-rendering 되어도 timer id를 유지시켜 새로운 timer가 할당되지않고 생성한 timer를 유지하기 위함으로 보임
use case2: dom element접근
import { useRef, useEffect } from 'react';
function AccessingElement() {
const elementRef = useRef();
useEffect(() => {
const divElement = elementRef.current;
console.log(divElement); // element 객체를 출력
}, []);
return (
<div ref={elementRef}>
I'm an element
</div>
);
}
use case2-1: focus
import { useRef, useEffect } from 'react';
function InputFocus() {
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus();
}, []);
return (
<input
ref={inputRef}
type="text"
/>
);
}
- 직접 Dom element에 mount시 focuse 되도록
- 최초 reder시에는 null 이고 effect 가 일어난 후 DOM 구조가 생성되어 Dom element를 할당함
- 그래서 useEffect시에 ref에 할당된 element를 제어하는것이 맞음
- ref는 useEffect나 event handler 내부에서 update 되어야함
참고자료: https://dmitripavlutin.com/react-useref-guide/
The Complete Guide to useRef() and Refs in React
How to use React.useRef() hook to create persisted mutable values (also known as references or refs), as well access DOM elements.
dmitripavlutin.com
'Front-end > React' 카테고리의 다른 글
Memoization(memo, useCallback) (0) | 2023.02.09 |
---|---|
controlled & uncontrolled input (0) | 2023.02.02 |
Next (0) | 2023.01.10 |
Styled-component (0) | 2022.12.05 |
React Query (0) | 2022.11.28 |