웹/React

[React] useEffect 안에서 fetch를 쓸 때 전에 setState를 하면 fetch 안에 값이 바뀔까?

wonin 2023. 4. 9. 16:58

🟩문제

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() 문이 끝나고 "전체 컴포넌트랜더링"이 실행되었다고 생각합니다.

 

 

728x90