컴포넌트 내에서 데이터를 저장하는 공간인 useRef를 배우고 기본변수, state, ref의 차이점을 배우다.
1. Ref
Ref를 사용하는 이유
기존에 컴포넌트 내에서 데이터를 저장하기 위해 state를 사용했다. 하지만 state는 값이 변함에 따라 리렌더링 된다는 단점이 있다. 리렌더링이 되면 컴포넌트에서 사용된 내부 변수가 초기화돼버린다. 리렌더링 되더라도 변수가 초기화되지 않는 것이 필요한 것이다. 이것을 해결해 주는 것이 바로 Ref이다.
Ref 특징
Ref로 데이터를 관리하면, Ref의 값이 변하더라도 컴포넌트가 리렌더링이 되지 않아서 불필요한 리렌더링 현상이 줄어들어 성능 저하를 방지한다. Ref로 데이터를 관리하는 컴포넌트가 state에 의해 리렌더링 되더라도 기본 변수와는 다르게 값이 초기화 되지 않는다.
Ref 활용
- 컴포넌트 내부에 저장 공간 관리
- DOM 요소에 접근하기 위한 방법
Ref가 활용되는 상황은 리렌더링이 일어나도 컴포넌트 내부에 데이터를 유지해야 할 경우, 특정 DOM 요소에 접근할 때이다. 특정 DOM 요소에 접근할 때 주로 사용된다. Ref로 input으로 값을 받을 수 있다. 기존의 자바스크립트의 경우에 input의 value를 가져오기 위해
const handleClick = () => {
let input = document.querySelector("input[type='text']")
console.log(input.value);
}
이런 식으로 버튼을 클릭했을 때 input값을 가져오는 방식을 사용하고 해당 DOM 요소에 접근하기 위해서 길고 긴 document.~~ 를 사용했다. React를 사용하는 이유 중 하나가 이렇게 길고 복잡하게 DOM에 접근하지 않고 간단하게 Ref로 특정 DOM요소에 접근할 수 있기 때문이다.
2. 기본 변수, state, Ref 차이점
전에 배웠던 state의 값이 변하면 리렌더링이 일어난다. 리렌더링이 일어나면 컴포넌트 내부의 기본 변수들은 초기화된다. 리렌더링이 일어나도 값이 변하지 않는 변수가 필요하기 때문에 ref를 배워야 한다. ref는 값이 변해도 리렌더링이 일어나지 않는다. state의 변화로 리렌더링이 일어나면 그때 ref의 변한 값이 화면에 보인다. 이해가 잘 되지 않는다면 직접 만든 그림 2의 표를 보고 이해해 보길 바란다.
3. useRef 활용
3 - 1. 저장공간의 useRef
// import './App.css';
import {useState, useRef} from "react"
function App() {
let countVar = 0;
const [countState, setState] = useState(0)
let countRef = useRef(0)
const handleClick1 = () => {
countVar += 1
console.log("var", countVar);
}
const handleClick2 = () => {
setState(countState + 1)
console.log("state", countState);
console.log("스테이트눌렀을때",countVar);
console.log("스테이트눌렀을때",countRef.current);
}
const handleClick3 = () => {
countRef.current += 1
console.log(("ref",countRef.current));
}
return (
<div className="App">
<p>var : {countVar}</p>
<p>state : {countState}</p>
<p>ref : {countRef.current}</p>
<button onClick={handleClick1}>var + 1</button>
<button onClick={handleClick2}>state + 1</button>
<button onClick={handleClick3}>ref + 1</button>
</div>
);
}
export default App;
기본변수, state, ref 변수를 만들어서 각 변수에 대응하는 버튼을 누를 때마다 +1씩 늘어나게해서 각 변수들의 차이점을 직접 확인해 보겠다. 각 버튼을 눌러서 해당 변수의 데이터 변화를 콘솔과 직접 화면으로 확인해 보겠다. 그리고 ref 변수의 값을 확인하는 방법은 ref.current를 사용하면 되는데 자세한 설명은 useRef 활용 2에서 설명하겠다.
첫 번째) 차례대로 var, state, ref 버튼을 눌렀다. var를 눌렀을 때 1로 바뀌고, state는 1을 추가하라는 신호만 보내는 거니까 0이 나오는게 맞다. ref도 1이 된 것을 볼 수 있다. state를 눌러서 리렌더링 되면서 var의 값은 1이지만 화면엔 보이지 않고, state는 바로 1로 변한다. ref를 1로 바꾸기 전에 state로 리렌더링 했기 때문에 ref는 값이 변했지만 화면에 1로 바뀌지 않았다.
두 번째) 첫 번째와 동일한 순서로 버튼을 클릭하였다. 첫 번째 과정에서 state의 값을 변화시킬 때 리렌더링이 일어나는 과정에서 기본 변수인 var는 1에서 0으로 초기화 된다. ref는 리렌더링이 일어남에도 불구하고 초기화가 되지 않는 특징이 있기 때문에 ref의 값은 1에서 2로 예측한 결과대로 진행되는 것을 볼 수 있다. 그리고 두 번째 ref를 누르기 전에(ref의 값이 1일 때) state로 리렌더링이 일어나서 화면에 ref의 값이 1로 보이는 것을 볼 수 있다. 현 상황에서 state의 값을 변경해서 리렌더링 과정을 주면 ref의 값이 현재 2니까 화면에 2로 바뀔 것이다. (그림 6)
3 - 2. 특정 DOM 접근의 useRef
import React, { useRef } from 'react'
const Ex01 = () => {
let inputRef = useRef()
const handleClick = () => {
let input = document.querySelector("input[type='text']")
console.log(input.value);
}
const handleClick2 = () => {
console.log(inputRef); // ref
console.log(inputRef.current); // input
console.log(inputRef.current.value); // input의 value 값
}
return (
<div>
<form>
<input type='text'/>
<input onClick={handleClick} type='button' value="클릭"/>
</form>
<form>
<input type='text' ref={inputRef}/>
<input onClick={handleClick2} type='button' value="클릭"/>
</form>
</div>
)
}
export default Ex01
ref를 활용해서 input의 값을 가져올 수 있다. 접근하고싶은 태그의 속성으로 ref = {ref변수}를 넣어주면 된다.
넣기 전에 ref를 선언해야 하는데 useRef함수를 사용한다. const ref변수 = useRef(value) / value는 ref의 초기값이다. state와 마찬가지로 파일의 상단에서 import로 useRef를 불러와야 사용할 수 있다.
const handleClick2 = () => {
console.log(inputRef); // ref
console.log(inputRef.current); // input
console.log(inputRef.current.value); // input의 value 값
}
그렇다면 왜 ref가 값이 아니라 current와 value까지 확인해야 하는 것일까? 그 이유는 간단하게 콘솔로 확인하면 된다.
ref의 콘솔 결과를 보면 객체형태로 되어있는 것을 볼 수 있다. 우리가 원하는 것은 input에 입력된 값을 원한다. 바로 value이다. value는 current안에 있기 때문에 input.current.value까지 해야 우리가 원하는 입력값에 접근할 수 있다.
'Front-End > React.js' 카테고리의 다른 글
[React.js] Life Cycle / useEffect (0) | 2023.09.05 |
---|---|
[React.js] Context (0) | 2023.09.03 |
[React.js] Filter 함수 (0) | 2023.08.29 |
[React.js] map 함수 / 컴포넌트 응용 (0) | 2023.08.28 |
[React.js] props와 state 차이점 / 주사위 게임 실습 (0) | 2023.08.24 |