useRef는 함수형 컴포넌트에서 ref를 쉽게 사용할 수 있도록 해준다.
Average 컴포넌트에서 등록 버튼을 눌렀을 때 포커스가인풋 쪽으로 넘어가도록 코드를 작성해 보자.
import React, { useState, useMemo, useCallback, useRef } from "react";
const getAverage = (numbers) => {
console.log("평균값 계산 중");
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setlist] = useState([]);
const [number, setNumber] = useState("");
const inputEl = useRef(null);
const onChange = useCallback((e) => {
setNumber(e.target.value);
}, []); // 컴포넌트가 처음 렌더링 될 때만 함수 생성
const onInsert = useCallback(() => {
const nextList = list.concat(parseInt(number));
setlist(nextList);
setNumber("");
inputEl.current.focus();
}, [number, list]); // number 혹은 list가 바뀌었을 때만 함수 생성
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value={number} onChange={onChange} ref={inputEl} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b> {avg}
</div>
</div>
);
};
export default Average;
useRef를 사용하여 ref를 설정하면 useRef를 통해 만든 객체 안의 current값이 실제 엘리먼트를 가리킨다.
컴포넌트 로컬 변수를 사용해야 할 때도 useRef를 활용할 수 있다.
로컬 변수란 렌더링과 상관없이 바뀔 수 있는 값을 의미한다.
클래스 형태로 작성된 컴포넌트가 로컬 변수를 사용해야 할 때는 다음과 같다.
import React, { Component } from "react";
class MyComponent extends Component {
id = 1;
setId = (n) => {
this.id = n;
};
printId = () => {
console.log(this.id);
};
render() {
return <div>My Component</div>;
}
}
이렇게 값이 바뀌어도 렌더링되지 않는 값을 의미한다.
함수형으로 작성하면 다음과 같다.
import React, { useRef } from "react";
const RefSample = () => {
const id = useRef(1);
const setId = (n) => {
id.current = n;
};
const printId = () => {
console.log(id.current);
};
return <div>refsample</div>;
};
export default RefSample;
이렇게 ref안의 값이 바뀌어도 컴포넌트에 렌더링되지 않는다는 점에 주의하자.