[React] useEffect 안에서 fetch를 쓸 때 전에 setState를 하면 fetch 안에 값이 바뀔까?
🟩문제
import React, { Component, useCallback, useEffect, useState } from "react";
const Test = () => {
const [count, setCount] = useState(0);
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(false);
const onClickHandle1 = useCallback(() => {}, []);
console.log(`전체 컴포넌트랜더링 count : ${count}`);
useEffect(() => {
console.log("useEffect 랜더링");
setCount(count + 1);
fetch(`https://jsonplaceholder.typicode.com/todos/1`)
.then((res) => res.json())
.then((data) => {
console.log("데이터 받기 성공", "count : ", count);
setProducts(data);
console.log(`data : ${data} count : ${count}`);
})
.finally(() => {
console.log("finally", count);
});
}, []);
return (
<div>
<button onClick={onClickHandle1}> click: {count}</button>
</div>
);
};
export default Test;
이런 예제를 들고 왔습니다.
위 코드가 어떻게 동작하실지 예상이 되시나요?
저는 처음에
"전체 컴포넌트 랜더링 count"
"useEffect 랜더링"
"데이터 받기 성공"
"data"
"finally"
이렇게 출력될 줄 알았습니다. 하지만 실제로 돌려보면
useEffect 다음에 전체컴포넌트 랜더링이 한번 더됩니다. setCount 때문입니다.
setCount 때문에 전체 컴포넌트가 랜더링 됩니다. 그러면 Test() 함수가 다시 실행됩니다.
🟩 그러면 useEffect 도 다시실행되야 하는거 아냐? 라고 생각했습니다. 아니였습니다.
왜냐하면 useEffect 훅이 의존성 배열에 빈 배열([])을 전달받았기 때문입니다. 의존성 배열에 빈 배열을 전달하면 useEffect 훅은 컴포넌트가 처음 렌더링될 때 한 번만 실행됩니다. 이후에는 의존성 배열에 포함된 값이 변경될 때마다 실행됩니다. 그러나 현재의 코드에서는 의존성 배열에 어떠한 값도 포함되어 있지 않으므로, useEffect 훅은 컴포넌트가 처음 렌더링될 때 한 번만 실행됩니다. 그 이후에는 count 값이 변경되어도 useEffect 훅은 실행되지 않습니다.
🟩 그럼 마지막에 전체 컴포넌트랜더링은 왜뜰까요?
fetch에서 then안에 setProducts()가 호출되었기 때문입니다.
then안에 비동기 실행될 때 setProducts도 호출 스택에 들어가게 됩니다. 상태 변경하는 것은 비동기로 이루어 진다고 합니다.
then 문 안에도 비동기로 실행되었을탠데요. 그 안에서 또 setProducts라는 비동기 함수를 실행한거 같습니다. 그래서 finally까지 console.log() 문이 끝나고 "전체 컴포넌트랜더링"이 실행되었다고 생각합니다.