Ref의 쓰임
1.변경시 변하지말아야하는 값을 설정하기 용이함
State의 변화->랜더링->컴포넌트 내부 변수들 초기화
Ref의 변화->랜더링 X->변수들의 값이 유지됨
-하지만 랜더링을 안해준다 뿐이지 ref값 자체는 변화가 됨. 따라서 useState를 통해 state가 변화되며 페이지가 랜더링되면, ref값도 갱신된다.
2. DOM 요소에 접근하기 쉬움
Ex. 로그인 화면에 들어오면 자동으로 로그인창 인풋에 클릭되어있게 하기
-js의 document.querySelector과 유사
import React, {useState, useRef} from "react";
const App = () => {
//useState 초기값 설정
const [count, setCount] = useState(0);
//useRef 초기값 설정
const countRef = useRef(0);
//setCount로 count를 바꾸는 함수 만들기
const increaseCountState = () => {
setCount(count+1);
};
//countRef.current 바꾸는 함수 만들기
const increaseCountRef = () => {
countRef.current = countRef.current +1;
};
return (
<div>
<p>State: {count}</p>
<p>Ref: {countRef.current}</p>
<button onClick={increaseCountState}>State 올려</button>
<button onClick={increaseCountRef}>State 올려</button>
</div>
);
};
export default App;
그 결과, State는 바뀌지만 Ref는 바뀌지 않는다
Ref와 변수 let의 차이는 무엇일까?
-let은 함수 내부에 있는 로컬함수의 경우, 함수가 재실행될 때에 초기화가 된다. 예컨대 아래의 코드를 보자
const App = () => {
const [renderer, setRenderer] = useState(0);
const countRef useRef(0);
let countVar = 0;
const doRendering = () => {
setRenderer(renderer + 1);
};
const increaseRef = () => {
countRef.current = countRef.current +1;
console.log("ref:", countRef.current);
};
const increaseVar = () => {
countVar = countVar + 1;
console.log("var:", countVar);
};
return{
<div>
<p>Ref: {countRef.current}</p>
<p>Var: {countVar}</p>
<button onClick={doRendering}랜더</button>
<button onClick={increaseRef}Ref 올려</button>
<button onClick={increaseVar}Var 올려</button>
</div>
};
위의 상황일 때, ref 버튼, var 버튼 모두 누르는대로 콘솔창에 count가 실행된다. 하지만 랜더를 하고 나면 ref는 값이 그대로 보존이 되지만 let은 함수가 재실행이 되면서 가장 상단에 정의를 했던 let countVar=0이 적용되어 초기값으로 초기화가 된다.
Ref의 값은 전생애주기에 거쳐 값이 유지가 된다. Mount되고나서 mount가 끝날 때까지.
이번에는 ref의 쓰임을 이해하기 위해, 랜더한 횟수를 세는 기능을 만들어보자
const App = () => {
const [count, setCount] = useState(1);
const [renderCount, setRenderCount] = useState(1);
useEffect(()=>{
console.log("랜더링");
setRenderCount(renderCount +1);
};
return{
<div>
<p>Count: {count}</p>
<button onClick={()=>setCount(count+1)>올려</button>
</div>
};
};
랜더링을 할 때마다 setRenderCount를 통해 renderCount라는 state에 +1을 해주는 방식은 어떨까? render이 될 때에 실행되는 함수이므로, useEffect를 사용하되 인자로 []를 주지 않음으로서 랜더링이 될 때마다 state를 바꿔주는 것이다.
-하지만 이 말을 잘 생각해보면, 랜더링이 무한히 되어버리게 된다. 랜더링이 되면 state를 바꾸어주고, 그렇게 되면 다시 랜더링이 될 것이고, 그렇게 되면 또 다시 useEffect가 실행되어 state를 바꾸어줄 것이기 때문이다.
따라서 useEffect에서 state를 바꿔주는 것이 아니라 ref를 바꿔주는 것이 좋을 것이다. 다음과 같이 말이다.
const App = () => {
const [count, setCount] = useState(1);
const renderCount = useRef(1);
useEffect(()=>{
renderCount.current = renderCount.current +1;
console.log("랜더링 수:", renderCount.current);
});
return{
<div>
<p>Count: {count}</p>
<button onClick={()=>setCount(count+1)>올려</button>
</div>
};
};
따라서 ref는 변화는 감지하되, 랜더링을 원하지 않을 때 사용한다.
import React from "react";
const App = () => {
return (
<div>
<input type="text" placeholder="username"/>
<button>Login</button>
</div>
};
};
export default App;