useEffect의 deps, 변수 state와 useRef 변수, 객체 변수의 차이를 정확히 알고 적용하자.
다음 코드에서 콘솔로그에 어떻게 찍힐지 예상해보자.
import "./styles.css";
import React, { useState, useEffect, useRef } from "react";
export default function App() {
const [, setChangeValue] = useState("a");
const strVariable = "a";
const objVariable = { a: "a" };
const refVariable = useRef({ b: "b" });
useEffect(() => {
setChangeValue("b");
setTimeout(() => {
setChangeValue("c");
}, 500);
}, []);
useEffect(() => {
console.log("strVariable", strVariable);
}, [strVariable]);
useEffect(() => {
console.log("objVariable", objVariable);
}, [objVariable]);
useEffect(() => {
console.log("refVariable", refVariable);
}, [refVariable]);
console.log("리렌더링")
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Edit to see some magic happen!</h2>
</div>
);
}
결과는 맨 아래에 두겠다.
위에서 아래로 읽음.
변수 다 읽고 엘리먼트들 렌더 후 useEffect()에 접근. setState()는 비동기기때문에 백그라운드로 간다.
setChangeValue("b")
, setChangeValue("c")
순서로 태스크 큐에 들어가고 다음 useEffect()에 접근한다. 차례대로 호출스택에서 바로 동기 코드들을 실행시킨다.
호출스택이 비면 이벤트 루프가 감지되어 태스크 큐에 있는 맨 앞의 setChangeValue("b")
부터 호출스택으로 끌어올린다.
setChangeValue("b")
가 실행되어 state값이 바뀌고 컴포넌트가 리렌더링 된다.
"a" === "a"
는 true이지만, { a: "a" } === { a: "a" }
의 결과는 false이다. 그러므로 useEffect()가 감지하고 objVariable을 다시 렌더링한다.
위에서부터 아래로 다 읽었으면 setChangeValue("b")
를 호출스택에서 지운다.
이벤트 루프가 호출스택이 비었다는 것을 감지하고 태스크 큐에 남은 setChangeValue("c")
를 호출스택으로 올리고 실행시킨다.