React Hooks - useRef
DOM 요소에 접근할 수 있도록 하는 React Hook
DOM 요소에 접근한다는 말은 결국, DOM 요소를 어딘가에 저장하고 그거를 갖다쓸 수 있게 하는 것
useRef 는
1. 저장공간으로서 기능
2. DOM 요소 접근 방법
useRef 사용방법
useRef의 반환값은 {} 객체이다.
그 객체 안에는 key가 current, value가 우리가 넣은 '초기값'이 들어 있다.
{current: '초기값'}
import { useRef } from 'react';
import './App.css';
function App() {
// ref: reference 참조
const ref = useRef('초기값');
console.log(ref);
return (
<div>
App
</div>
);
}
export default App;
useRef의 value 값을 변경할 수 도 있다.
useRef도 객체니까, value 값으로 접근하는 방식 그대로 이용하여 변경값으로 값을 바꾼다.
import { useRef } from 'react';
import './App.css';
function App() {
// ref: reference 참조
const ref = useRef('초기값');
console.log(ref);
ref.current = '변경값';
console.log("ref2", ref);
return (
<div>
App
</div>
);
}
export default App;
이렇게 설정된 useRef 의 값은 컴포넌트가 계속해서 랜더링 되어도 unmount 전까지 값을 유지함
이러한 특성을 가진 덕분에 useRef는 두 가지의 용도로 사용된다
1. 저장공간
- state와 비슷한 역할. 단 sstate는 변화가 일어나면 다시 렌더링이 일어남. 따라서 내부 변수들은 초기화가 된다.
- ref에 저장한 값은 렌더링을 일으키지 않는다. 즉, ref의 값 변화가 일어나도 렌더링으로 인해 내부 변수들이 초기화 되는 것을 막을 수 있다.
-컴포넌트가 100번 렌더링되도 ref에 저장한 값은 유지된다.
** state는 리렌더링이 꼭 필요한 값을 다룰 때 쓰기
** ref는 리렌더링을 발생시키지 않는 값을 저장할 때 사용하기
예시
버튼을 누를때마다 -> 로직에 의해 반환된 값이 리랜더링이 되며 -> 화면에서 값이 계속 올라간다
ref로 설정된 버튼을 누를때마다 -> 값이 바뀌지만 -> 리랜더링(화면에 보여지는과정)이 되지 않아 -> 화면에서 값이 유지가 된다.
import { useRef } from 'react';
import { useState } from 'react';
import './App.css';
function App() {
const [count, setCount] = useState(0);
const countRef = useRef(0);
const plusStateCountBtnHandler = () => {
setCount(count+1);
}
const plusRefCountBtnHandler = () => {
countRef.current++; // 1을 더한다
console.log("countRef 버튼 눌린 횟수",countRef.current);
}
return (
<div>
<div style={{backgroundColor: "yellow",}}>
state 영역입니다. {count} <br />
<button onClick={plusStateCountBtnHandler}>state 증가</button>
</div>
<div style={{backgroundColor: "pink",}}>
ref 영역입니다. {countRef.current} <br />
<button onClick={plusRefCountBtnHandler}>ref 증가</button>
</div>
</div>
);
}
export default App;
2. DOM 요소에 접근하는 방법
예시
: 처음 화면이 나올 때 아이디 입력창에 포커싱이 가게 한다
먼저, 아이디 입력창을 지정해야 한다! 즉, 이 입력창에 대한 레퍼런스를 갖고 있어야 한다.
- const idRef = useRef('');
- 입력창 input 태그 속성에 ref={idRef} 를 넣기
- useEffect 반환값에 idRef.current.focus() 넣기
import { useEffect } from 'react';
import { useState } from 'react';
import './App.css';
function App() {
const idRef = useRef('');
useEffect(()=>{
idRef.current.focus(); //focus는 API
})
return (
<div>
<div>
아이디: <input type="text" ref={idRef}/>
</div>
<div>
비밀번호: <input type="password"/>
</div>
</div>
);
}
export default App;
연습
아이디가 10자리 입력되면 자동으로 비밀번호 필드로 이동하도록 하기
import { useEffect } from 'react';
import { useRef } from 'react';
import { useState } from 'react';
import './App.css';
function App() {
const [id, setId] = useState('');
const [pw, setPw] = useState('');
const idRef = useRef('');
const pwRef = useRef('')
useEffect(()=>{
idRef.current.focus(); //focus는 API
},[])
useEffect(()=>{
if(id.length >= 10){
pwRef.current.focus();
}
},[id])
return (
<div>
<div>
아이디: <input value={id} onChange={(event)=> {
setId(event.target.value);
}} type="text" ref={idRef}/>
</div>
<div>
비밀번호: <input value={pw} onChange={(event)=> {
setPw(event.target.value);
}} type="password" ref={pwRef}/>
</div>
</div>
);
}
export default App;
onChange 함수안에 id.length ≥ 10 를 넣지 않은 이유?
batch 업데이트 방식을 사용하고 있기 때문이다.
setId(event.target.value)에서 10번째 문자를 입력했을 때, 리액트는 그 아래 있는 함수를 아직 해결하지 않았기때문에 데이터 업데이트가 아직 안된상태로 그 아래 함수까지 모두 끝나야 if문의 id가 비로소 10으로 업데이트가 된다. 따라서 11자가 들어간 후에 비밀번호 입력창으로 커서가 포커싱되는 것이다. 따라서 앞으로 리액트의 이러한 배치 업데이트 방식을 잘 이해하고 로직을 짜야 한다.
'부트캠프 개발일지 2023-2024 > React 리액트' 카테고리의 다른 글
[6주차] 리액트숙련: React Hooks - 최적화(React.memo, useCallback, useMemo) (0) | 2023.11.08 |
---|---|
[6주차] 리액트숙련: React Hooks - useContext(Context API) (0) | 2023.11.08 |
[6주차] 리액트숙련: React Hooks - useEffect (0) | 2023.11.08 |
[6주차] 리액트숙련: React Hooks - useState (0) | 2023.11.08 |
[6주차] 리액트숙련: GlobalStyles, Sass, css reset (0) | 2023.11.08 |