-
[React] useRef는 왜 써야하는가?React 2024. 2. 25. 21:57
useState 장점과 변수의 장점을 합친 것.
useRef란 레퍼런스를 사용하기 위한 훅.
그렇다면 레퍼런스란?
리액트에서 레퍼런스란 특정 컴포넌트에 접근할 수 있는 객체.
레퍼런스 객체에 current 객체가 있음. 이는 현재 참조하고 있는 element.
useRef는 그 값이 변하더라도 렌더링을 발생시키지 않는다.
1. 사용법
const exampleRef = useRef(초기값);
2. useRef를 왜 사용해야 하는가?
a. 저장공간으로서의 장점
값을 저장할 필요가 있는 변수가 있을 때 사용하면 좋음. 단, UI에 보일 필요가 없는 친구들을.
예시로,
import { useState } from "react"; export default function Example1() { const [count, setCount] = useState(""); return ( <> <div>count : {count}</div> <button onClick={() => setCount((prev) => prev + 1)}>1씩증가!</button> </> ); }
이런 경우에는 count가 버튼 클릭 시 1씩 잘 증가되는 것을 볼 수 있다.
퀴즈)) 그렇다면 변수의 경우엔 어떻게 될까??
import { useState } from "react"; export default function Example1() { const [count, setCount] = useState(""); let 변수 = 0; return ( <> <div>count : {count}</div> <div>변수 : {변수}</div> <button onClick={() => setCount((prev) => prev + 1)}>count 1씩증가!</button> <button onClick={() => 변수++}>변수 1씩증가!</button> </> ); }
답 1. 실습 참고
또한!!
답 2. 실습 참고
이제 useRef를 이용해보자.
const refCount = useRef(null); . . . <button onClick={() => console.log('ref', refCount)}>ref를 콘솔로그 찍으면?</button>
우선적으로 useRef에는 어떤 값이 들어가있는가를 확인해보기 위해 콘솔을 찍어 보았다.
오호! ref안에는 객체가 들어오고, 그 객체 안에는 current라는 키 값이 있다.
const refCount = useRef(null); return <div>refCount : {refCount.current}</div> <button onClick={() => refCount.current++}>ref 1씩 증가!</button> </> ); }
ref 1씩 증가! 라는 버튼을 클릭해도 화면 ui에는 그려지지 않는다.
그러나
재렌더링이 일어난 이후에는 증가한 ref값을 볼 수 있을 것이다.
이렇게 useRef는 ui에 보여지지 않지만 값을 저장하는 용도로 사용할 수 있다.
다만, 실무에서 이런 용도로 사용할 일이 많을지는 더 공부해봐야 할 것 같다.
b. DOM을 선택하는 기능
useRef의 가장 좋은 기능이라고 할 수 있을 것 같다.
javascript에서 document.querySelector와 같은 것들을 사용하며 DOM에 접근하고는 했는데,
react를 배우면서 생각해보면, document.querySelector과 같은 것들을 사용한 적이 없었다는 것을 알 수 있을 것이다.
그러나, 우리는 react에서도 직접적으로 접근해야할 필요성이 있다.
공식문서에서는 이 경우에 접근하도록 권장한다.
Ref의 바람직한 사용 사례는 다음과 같습니다.
- 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때.
- 애니메이션을 직접적으로 실행시킬 때.
- 서드 파티 DOM 라이브러리를 React와 같이 사용할 때.
출처: https://ko.legacy.reactjs.org/docs/refs-and-the-dom.html
Ref와 DOM – React
A JavaScript library for building user interfaces
ko.legacy.reactjs.org
간단한 예시로, input창에 버튼 클릭 시 focus 되는 로직을 작성해보자.
function App() { const inputRef = useRef(0); const clickBtn = () => { inputRef.current.focus(); }; return ( <> <input ref={inputRef} type="text" /> <button onClick={clickBtn}>클릭해봐</button> </> ); } export default App;
input에 ref라는 속성을 주어 dom에 직접 접근할 수 있다.
또한 설정해둔 ref (inputRef) 속 current 키값에 focus 속성을 주어 버튼 클릭 시 input에 focus되는 로직을 쉽게 구현할 수 있다.
이번 프로젝트를 통해 useRef의 필요성을 알게되었는데, 이 DOM을 선택할 수 있다는 장점 덕분에 알게되었다.
아이콘 클릭 시 브라우저 기본 input type='time'을 보여줘야 하는데, 처음에 useRef를 사용해야한다는 생각조차 하지 못했었기 때문에,
그 경험을 공유해보고자 한다.
interface TimePickerProps { onSelect: (selectedTime: string) => void; } const TimePicker = ({ onSelect }: TimePickerProps) => { const clockRef = useRef<HTMLInputElement>(null); const handleIconClick = () => { clockRef.current?.showPicker(); }; return ( <> <S.TextField onClick={handleIconClick}> <S.Input placeholder='시작 시간을 선택해주세요' value={selectedTime} onChange={(e) => setSelectedTime(e.target.value)} /> </S.TextField> <S.IconField> <input ref={clockRef} type='time' id='clock' onChange={(e) => handleTimeSelect(e.target.value)} style={{ display: 'flex', opacity: 0 }} /> <label htmlFor='clock'> <IcUnselectedClock style={{ width: '2.4rem', height: '2.4rem' }} /> </label> </S.IconField> </> ); }; export default TimePicker;
전체 코드를 가져오지는 않고, 일부만 가지고 왔다.
ref를 사용하지 않을 때는, 기본으로 출력되는 input type='time' 이 굉장히 거슬렸고,
화면 ui에 맞지 않았으며, 같은 팀 디자이너 분들이 이를 가려주기를 원하셨다.
분명히 방법이 있을 것이라고 생각하고 찾아본 결과, useRef를 사용하게 되었다.
시간을 선택할 수 있는 input에 ref를 만들어주고,
기본으로 출력되는 input type='time' 을 opacity 0을 주어 안보이게끔 처리한 후에,
이 DOM에 직접 접근하여 해당 영역 클릭 시 clockRef.current.showPicker()로 브라우저 기본 시간 선택 창을 나타낼 수 있게 하였다.
**여기서 showPicker란?
HTMLInputElement.showPicker() 메소드는 input 요소에 대한 브라우저 선택기를 표시합니다.
'React' 카테고리의 다른 글
useContext (ContextAPI) 란? (0) 2024.03.12 언젠가는 쓸 useLayoutEffect... (useEffect vs useLayoutEffect) (0) 2024.03.03 모던 리액트 Deep dive - 클래스, 클로져 (3) 2024.02.18 모던 리액트 Deep Dive - 리액트 개발을 위해 꼭 알아야 할 JS (1) 2024.02.12 Funnel에서의 상태관리 고민 (0) 2024.01.30