12. useRef 로 useRef 로 컴포넌트 안의 변수 만들기 · GitBook
12. useRef 로 useRef 로 컴포넌트 안의 변수 만들기 · GitBook
자료를 보는 중에 질문이 생겨 댓글 남깁니다. 혹시 아래와 같은 방법을 지양하는 이유에 대해서 알 수 있을까요? useRef를 반드시 써야하는 것인지 궁금해서 여쭙니다. :)
객체를 직접 선언
const nextId = { current: 4 };
let을 이용한 변수 선언
let nextId = 4;
@joeunha 리렌더링 없이 변수값의 변화를 이용하기 위해서 아닐까요?
nextId.current += 1; 이렇게 변수 값이 변화하는데 어떻게 const 로 선언할 수 있는지 궁금합니다..! 직접적으로 nextId의 값이 바뀌는 것이 아니라 current 속성 값이 바뀌는 거라서 가능한건가용...? 아시는 분 있으면 답변 달아주시면 감사하겠습니다 ㅎㅎ
@haileychoi15 nextId는 ref 객체라서 속성값은 바뀔 수 있어요
@joeunha
useRef는 일반적인 자바스크립트 객체입니다 즉 heap 영역에 저장됩니다
그래서 어플리케이션이 종료되거나 가비지 컬렉팅 될 때 까지 참조할 때 마다 같은 메모리 주소를 가지게 되고
같은 메모리 주소를 가지기 때문에 === 연산이 항상 true를 반환하고, 값이 바뀌어도 리렌더링 되지 않습니다.
하지만 함수 컴포넌트 내부에 변수를 선언한다면, 렌더링 될 때마다 값이 초기화 됩니다. 그래서 해당 방법을 지양하는 것 같습니다 :)
아하! 답변 감사합니다. @SeoziMadeInKorea @min-elena-k
이미 수개월이 지났지만 이후의 독자들을 위해 혼란을 야기할 수 있는 댓글들을 정정하자면 @hajoeun님의 질문은 useRef 대신에 useRef의 반환값처럼 어떤 데이터를 감싸는 wrapper 객체를 만들면 되지 않느냐입니다.
컴포넌트는 그 컴포넌트의 state나 props가 변경될 때마다 호출되는데(re-rendering), 함수형 컴포넌트는 일반 자바스크립트 함수와 마찬가지로 호출될 때마다 함수 내부에 정의된 로컬 변수들을 초기화합니다. 따라서
const nextId = { current: 4 };
nextId.current는 함수가 호출될 때마다 4입니다.
반면 useRef로 만들어진 객체는 React가 만든 전역 저장소에 저장되기 때문에 함수를 재 호출하더라도 마지막으로 업데이트한 current 값이 유지됩니다.
@hajoeun 님의 질문에 대한 답은 https://ko.reactjs.org/docs/hooks-reference.html#useref 위 링크에 있는 것 같습니다.
useRef의 또 다른 역할
- 컴포넌트 안에서 조회 및 수정 할 수 있는 변수 관리
- useRef로 관리되는 변수는 값이 바뀌어도 컴포넌트가 리렌더링 되지 않습니다.
useRef Hook 은 DOM 을 선택하는 용도 외 컴포넌트 안에서 조회 및 수정 할 수 있는 변수를 관리 **useRef 로 관리하는 변수는 값이 바뀌어도 컴포넌트 리렌더링 X 이 값을 수정 할때에는 .current 값을 수정, 조회 할 때에는 .current 를 조회
https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables
hook FAQ 에 useRef 를 값을 저장하기 위한 변수로 사용하는 것에 대한 내용이 있네요. 즉 클래스의 instance 속성 이라고 이해 하면 될거 같군요.
" 리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고 나서 그 다음 렌더링 이후로 업데이트 된 상태를 조회 할 수 있는 반면, useRef 로 관리하고 있는 변수는 설정 후 바로 조회 할 수 있습니다."
이 부분이 잘 이해가 되지 않습니다. setState를 통해서 값이 변경되면 re-rendering이 되기 전에는 값이 변하지 않고 re-rendering이 된 이후에 비로소 값이 변경이 된다는 것인가요? 그리고 함수 컴포넌트는 재호출시마다 로컬변수들을 초기화 하기 때문에 로컬변수사용 대신에 useRef를 사용해서 값을 유지시키는 건가요?
@123rudgks 님의 질문에 혹여나 도움이 될까해서 남깁니다. https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/ 첫번째 질문은 위의 리액트 컴포넌트의 라이프사이클 메소드를 참고하시면 좋을 것 같습니다. 값이 변경된 시점 후부터 리렌더링 전까지 state 에 접근하여 값 변경이 가능합니다. 즉, setState를 통해 값을 변경하면 리렌더링이 일어나 변경한 값을 화면에서 확인할 수 있지만 리렌더링이 일어나기 전의 시점까지는 값이 바뀌더라도 화면에서 그 값을 바로 확인할 수 없는 것입니다..
두번째 질문은 채팅창의 스크롤을 예로 들면 우리가 채팅을 입력하며 함수컴포넌트를 재호출하게 될 때 스크롤을 움직이게 되면 스크롤의 state 값이 변하게되는데 값이 변하면 리렌더링이 일어나니 계속해서 리렌더링이 일어날겁니다. 이를 useRef 를 사용하여 동일한 참조값을 유지한다면 스크롤의 상태에 관계없이 리렌더링은 일어나지 않을 것 같습니다.
혹시나 제가 잘못 이해하고 설명한 부분이 있다면 적극적인 피드백 부탁드립니다.
현재 예시에서 nextId 변수를 useRef로 관리하면 state로 관리하는것에 비해서 어떤 이점이 생기는지 궁금합니다. 현재 컴포넌트 내부의 다른 state들은 (inputs, users) 값이 변경됨에 따라서 화면도 갱신이 되어야하는 것에 비해서 nextId 는 값의 변경을 즉각적으로 화면에 반영해야하는 요소가 아니기 때문에 nextId 를 state로 뒀을 때 발생하는 불필요한 재렌더를 방지하기 위함인가요?
당신은 천사입니다
본문도 본문이지만 댓글써주시는 분들의 퀄리티도 더할 나위 없네요.
let변수를 function 컴포넌트 바깥 scope에 선언하면 useRef()를 사용하지 않아도 되지않나요?