Skip to content

Instantly share code, notes, and snippets.

@json9512
Last active October 14, 2022 08:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save json9512/ef28abf2429c639ccbdd6b48c7c3efe5 to your computer and use it in GitHub Desktop.
Save json9512/ef28abf2429c639ccbdd6b48c7c3efe5 to your computer and use it in GitHub Desktop.
react useRef test
import { useEffect, useRef, useState } from 'react';
/* 설명:
React Strict mode를 해제한 상태에서 테스트해봤습니다.
1. 페이지에 Increase 버튼이 있음. 누르면 onClick 함수 실행됨
2. 페이지가 렌더된 후, useEffect에서 setTimeout을 실행시킴. setTimeout은 2초 뒤 console에 출력함
3. JSX에 각 값들이 (x.a = 일반 JS 객체, code = react의 state, s.current = useRef를 통해 받은 객체의 current 값) 표시되도록 되어있음
*/
export default function Home() {
const s = useRef();
const [code, setCode] = useState(0);
const x = { a: 1 }; // 가설 2: useMemo를 사용해서 x를 생성해보세요.
s.current = code;
// x.a = code; // CASE 3
useEffect(() => {
console.log('rendered');
setTimeout(() => {
console.log(x.a);
console.log(code);
console.log(s.current);
}, 2000);
return () => console.log('cleanup');
}, []);
return (
<div style={{ height: '100vh', marginTop: '40vh' }}>
<button
onClick={() => {
x.a += 1;
/* 아래의 setCode를 코멘트 처리해보시면됩니다 */
setCode((c) => c + 1);
}}
>
Increase
</button>
<br />
{/*
보여지는 창은 state change (setCode)가 일어나면 바뀜
*/}
x.a: {x.a}, state: {code}, ref: {s.current}
</div>
);
}
/*
CASE 1: onClick 함수의 setCode를 코멘트 처리하고 실행
1. 새로고침 후, Increase를 클릭함
2. setTimeout에 의해 2초 뒤, 클릭 횟수만큼 console x.a가 올라감
3. 브라우저는 업데이트 되지 않음. x: 1인 상태
CASE 2: onClick 함수의 setCode를 코멘트 처리하지 않고 실행
1. 새로고침 후, Increase를 클릭함
2. setTimeout에 의해 2초 뒤, 클릭 횟수만큼 console에 s.current 값이 올라감. x.a는 2로 고정됨. code는 0으로 고정됨.
3. 브라우저는 클릭 마다 업데이트 됨. x: 1인 상태로 고정, code와 s.current는 클릭 수 만큼 올라감
설명:
콘솔 부분:
CASE 1의 경우, x.a는 일반 객체고 onClick에서 객체의 값만 바꾸고 있음.
React 입장에서는 re-render 조건이 성립하지 않기 때문에 우리가 클릭할때마다 x 객체는 동일한 객체여서 x.a가 2로 고정되지 않고 클릭 수 만큼 더해짐.
JSX 부분:
JSX에는 x.a가 1로 고정되는 이유는, JSX가 컴파일 될 시점에는 onClick이 발생하기전이고 x.a는 초기값이 1이니까 브라우저에는 1로 보임.
콘솔 부분:
CASE 2의 경우, onClick을 하면 setCode가 돌게되고 state change가 발생하기 때문에 react는 re-render를 하게됨.
이때 x = { a: 1 }이라는 코드도 다시 실행되게 되는데, 항상 새로운 객체를 만드는 것이기 때문에 x.a는 항상 1임.
여기서 onClick으로 x.a += 1이 실행되니까 값이 2로 고정이됨.
JSX부분:
JSX에는 x.a가 1로 고정되는 이유는, JSX가 컴파일 될 시점에는 onClick이 발생하기전이고 x.a는 항상 1이니까 브라우저에는 1로 보임.
반면에 useRef로 받은 s의 경우 같은 객체고, s.current에 항상 업데이트된 code를 넣어주니까 code가 업데이트 됨을 볼 수 있음
----
가설: x.a에 업데이트된 code를 넣어주면 useRef와 똑같이 동작할까?
CASE 3: s.current = code와 같이 x.a = code로 할당할 경우 어떻게 되는가
1. 새로고침 후, Increase를 클릭함
2. setTimeout에 의해 2초 뒤, 클릭 횟수만큼 console에 s.current 값이 올라감. x.a는 1로 고정됨. code는 0으로 고정됨
3. 브라우저는 클릭 마다 업데이트 됨. x, code와 s.current는 클릭 수 만큼 올라감
콘솔 부분:
setTimeout이 dispatch되는 시점에 x.a = code 일텐데, code의 값이 이때는 1이어서 콘솔 창에서 x.a가 1로 고정되는 것 같음.
x.a가 1로 고정되는 이유는 useState의 초기값이 0 이기 때문인듯. 사실상 CASE 2와 같은 동작 원리를 가지고 있음.
code는 그대로 0으로 고정.
s.current는 클릭 수 만큼 올라감
JSX 부분:
x.a = code니까 항상 새로운 상태값을 보고있음. JSX 렌더시에 x.a, code, s.current 모두 동일한 값이 들어가게됨.
----
가설 2: 그렇다면 일반 JS 객체인 x에 useMemo를 사용하게 되면 useRef와 동일한 효과를 기대할 수 있는가?
정답은: yes. 동일하게 작동합니다. console에 클릭 수 만큼 x.a가 업데이트되는 것을 볼 수 있음.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment