→ ref object는 { current: value } 생김 → 그리고 우리가 인자로 넣어준 초기값은 ref안에 있는 current에 저장 ↓
• ref object는 수정이 가능하기 때문에 언제든 우리가 원하는 값으로 수정가능! ↓
• 반환된 ref는 컴포넌트의 전생에주기를 통해 유지가 됨
→ 컴포넌트가 계속해서 렌더링되어도, 컴포넌트가 unmount되기 전꺼지는 값을 그대로 유지 가능
• ref는 state와 비슷하게 어떠한 값을 저장해두는 공간으로 사용
• State의 변경하면 → 자동으로 컴포넌트가 렌더링 → (함수형 컴포넌트는 말그대로 함수라서 리렌더링을 하면 함수가 다시 불러지는거라서) 내부에있는 변수들이 다시 초기화 됨
→ 그래서 원하지 않는 렌더링때문에 곤혹을 겪음
그러면 State말고 ref에 저장하는건 무슨 차이?
• Ref의 값을 아무리 변경해도 → 컴포넌트는 다시 렌더링 ❌ → 그래서 변수들의 값이 유지 됨
• State의 변화(컴포넌트가 아무리 렌더링 되어도) → 그래도 Ref에 저장된 값은 유지됨
→ 그래서 변경시 렌더링 되지 말아야 하는 값을 다룰때 아주 유용!
• input 요소를 클릭하지 않아도, focus를 주고 싶을 때 많이 사용
ex) 로그인 화면이 보여졌을때, id를 넣는 input을 굳이 클릭하지 않아도 자동적으로 focus가 되어있게 해주면, 바로 키보드를 사용해서 id를 입력할 수 있음!
→ Ref를 사용하면 손쉽게 input에 접근해서 이런 작업을 쉽게 할 수 있음!
→ 바닐라 자바스크립트의 Document.querySeletor()
의 역할을 함
import React, { useState } from 'react';
const App = () => {
const [count, setCount] = useState(0); //count라는 State가 있고, 0으로 초기화
console.log('🍎렌더링...'); //여기에 consosle로 확인하면 State가 변경될때마다 App이 console에 출력됨
const increaseCountState = () => {
setCount(count + 1); //이 함수는 불릴때마다 setCount를 사용해서 count를 하나씩 증가시켜줌
};
return(
<div>
<p>State: {count}</p> //count State를 보여주는 p태그
<button onClick={increaseCountState}>State 올려</button> // 이 버튼을 누를때마다 inCreaseCountState함수가 불림
//리액트에서 State가 변경된다는 것은 컴포넌트가 다시 렌더링 됨
//이 컴포넌트는 함수형 컴포넌트라서 App이라는 함수가 다시 불려진다는 것
</div>
);
}
export default App;
import React, { useState, useREf } from 'react';
const App = () => {
const [count, setCount] = useState(0);
const countRef = useRef(0);
console.log(countRef); //console로 확인하면 {current: 0} 출력되는거 확인 가능
//→ Ref는 하나의 object이고, Ref안에는 current라는 값이 있고, current안에는 우리가 설정한 초기값 0을 가짐!
//그래서 Ref안에 있는 값에 접근하고 싶으면 countRef.current 이런식으로 접근!
console.log('🍎렌더링...');
const increaseCountState = () => {
setCount(count + 1);
};
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}>Ref 올려</button>//버튼이 눌릴때마다 State가 아닌 Ref가 증가 되도록!
</div>
);
};
export default App;
여기서 알수있는 Ref의 장점은 만약 컴포넌트 안에 자주 바뀌는 값을 State안에 넣어 놓으면?
→ 값이 바뀔때마다 렌더링되고 또 렌더링 됨 → 이러면 성능에 안좋은 영향을 미침 → 여기서 State가 아니라 Ref를
사용해주면 값이 아무리 바껴도 렌더링을 발생시키지 않아서 성능에 좋음!
import React, { useState, useREf } from 'react';
const App = () => {
const [renderer, setRenderer] = useState(0);
const countRef = useRef(0);
let countVar = 0;
const increaseRef = () => {
countRef.current = countRef.current + 1;
};
const increaseVar = () => {
countVar = countVar + 1;
};
const doRendering = () => {
setRenderer(renderer + 1);
}
//Ref의 변화도 렌더링 ❌ → 화면 업데이트 ❌
//변수의 변화도 렌더링 ❌ → 화면 업데이트 ❌
// → 화면을 업데이트 해주는 State가 필요함
return(
<div>
<p>Ref: {countRef.current}</p>
<p>Var: {countVar}</p>
<button onClick={doRendering}>렌더</button> //누르면 UI에 반영하게끔
<button onClick={increaseRef}>Ref 올려</button>
<button onClick={increaseVar}>Var 올려</button>
// 이렇게 만들고 렌더 버튼을 누르면 Ref는 화면에 렌더링 되고, Var는 안됨
// 우리의 컴포넌트가 렌더링 된다는 것은 컴포넌트를 나타내는 함수가 다시 불린다는 것
// → 함수가 불리면 불릴때마다 함수내부의 변수가 초기화됨(함수가 불리때마다 countVar변수는 함수가 불릴때마다 0으로 초기화!)
// 하지만 Ref는 우리 컴포넌트가 계속 렌더링되어도 값을 유지
// → 왜냐하면 Ref의 값은 컴포넌트의 전생에주기를 통해 유지되기때문
// 이말인 즉슨 컴포넌트가 브라우저에 mounting된 시점부터 mount해제된 시점까지 같은 값 유지 가능
);
};
export default App;
import React, { useState, useREf } from 'react';
const App = () => {
const [count, setCount] = useState(1);
const [renderCount, setRenderCount] = useState(1);
useEffect (() => {
console.log("렌더링!");
setRenderCount(renderCount + 1);
});
//몇번 렌더링 됐는지 확인할때 이렇게 작성하면 무한루프 걸림...
// 왜냐하면 "올려"버튼을 누르면 useState안에 setCount가 업데이트 되기 때문에 해당 useEffect가 불림
//문제는 useEffect안에도 renderCount State를 업데이트 하는 코드가 있음
//count State 업데이트 됐고 → useEffect 불렸고 → 그리고 renderCount도 업데이트 됨
//→ 그러면 또 useEffect 불리고 → 또 renderCount불리고 이렇게 무한히 반복됨
return(
<div>
<p>Count: {count}</p> //현재 카운트 값 출력
<button onClick={() => setCount(count + 1)}>올려</button>
//버튼을 누를때마다 count state를 하나씩 증가시켜주는 버튼
</div>
);
};
export default App;
import React, { useState, useREf } from 'react';
const App = () => {
const [count, setCount] = useState(1);
const renderCount = useRef(1);
useEffect (() => {
renderCount.current = renderCount.current + 1;
console.log("렌더링 수:", rednerCount.current);
});
//이렇게 작성하면 console에 "올려"버튼을 누를때마다 렌더링수가 무한루프에 걸리지 않고 잘 나옴
// 이유는 ref는 리렌더링을 발생시키지 않음
return(
<div>
<p>Count: {count}</p> //현재 카운트 값 출력
<button onClick={() => setCount(count + 1)}>올려</button>
</div>
);
};
export default App;
useRef는 변화를 감지함, 하지만 그 변화가 렌더링을 발생시키면 안되는 어떤 값을 다룰때 유용하게 사용가능!