inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

타입스크립트로 배우는 리액트(React.js) : 기초부터 최신 기술까지 완벽하게

fetch - 2 (loading)

react-fetch -2 (loading) 에러

29

5647kr

작성한 질문수 8

0

react 19 및 ESLint (exlint-plugin-react-compiler 또는 최신 react-hooks 규칙)에서 새로 추가된 규칙으로 발생하는 문제가 있습니다.



  useEffect(() => {
    setIsLoading(true);
    fetch("http://localhost:3000/posts")
      .then((reponse) => {
        return reponse.json();
      })
      .then((data) => setPosts(data))
      .finally(() => {
        setIsLoading(true);
      });
  }, []);

useEffect 내부에서 조건 없이 동기적으로 setState를 호출하면 컴포넌트가 마운트되자마자 불필요한 리렌더링 연쇄가 일어나기 때문에 위와 같은 코드 작성을 금지한다고 하는데, 최신 문법에 맞는 방법은 어떻게 작성하면 좋을지 궁금합니다

react react-router redux-toolkit zustand react.js

답변 2

0

수코딩

안녕하세요.

해당 오류는 말씀하신 것처럼 useEffect 내부에서 조건 없이 동기적으로 setState를 호출할 경우, 컴포넌트가 마운트되자마자 불필요한 리렌더링이 연쇄적으로 발생하기 때문입니다.

따라서 동기적으로 setState를 호출하지 않도록 처리하면 됩니다. 가장 간단한 우회 방법으로는 window.setTimeout(() => {}, 0)과 같은 패턴을 사용해 비동기적으로 상태를 변경하는 방법이 있습니다.

다만 위 코드에서는 fetch 자체가 이미 비동기적으로 동작하기 때문에, 별도로 setTimeout을 사용할 필요는 없습니다. 초기 isLoading 상태를 true로 설정한 뒤, fetch가 완료되었을 때 상태를 변경하는 방식으로 처리할 수 있습니다.

const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  fetch("http://localhost:3000/posts")
    .then((response) => {
      return response.json();
    })
    .then((data) => setPosts(data))
    .finally(() => {
      setIsLoading(false);
    });
}, []);

이렇게 하면 컴포넌트가 처음 렌더링될 때는 isLoadingtrue이고, fetch가 완료된 이후 false로 변경되므로 불필요한 동기적 상태 변경을 피할 수 있습니다.

추가로 궁금한 점이 있으시면 언제든지 다시 질문해주세요.

감사합니다.

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. 5647kr님.

질문하신 내용과 가장 가까운 기존 질문은 useEffect 내부에서 비동기 요청을 실행하고 로딩 상태를 관리하는 사례입니다.

useOptimistic 실전-1 useState

useEffect가 실행될 때 setIsLoading(true)를 호출하기보다는, 로딩 상태의 초기값을 true로 설정하는 방식이 적절합니다. 컴포넌트가 처음 렌더링될 때 이미 데이터를 불러오는 중이기 때문입니다.

const [posts, setPosts] = useState<Post[]>([]);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  let ignore = false;

  fetch("http://localhost:3000/posts")
    .then((response) => response.json())
    .then((data) => {
      if (!ignore) {
        setPosts(data);
      }
    })
    .catch((error) => {
      console.error(error);
    })
    .finally(() => {
      if (!ignore) {
        setIsLoading(false);
      }
    });

  return () => {
    ignore = true;
  };
}, []);

핵심은 다음과 같습니다.

  • isLoading의 초기값을 true로 지정하여 useEffect 내부의 불필요한 setIsLoading(true)를 제거합니다.
  • 요청이 완료되면 finally에서 setIsLoading(false)로 변경합니다.
  • 현재 코드의 finally에서 setIsLoading(true)로 되어 있는 부분은 로딩이 끝난 뒤에도 계속 로딩 상태가 유지되므로 false가 되어야 합니다.
  • ignore 플래그는 컴포넌트가 언마운트된 뒤 요청이 완료되는 경우 상태 업데이트를 방지하기 위한 처리입니다.

다만 React 19의 최신 ESLint 규칙은 useEffect 내부에서 동기적으로 상태를 변경하는 패턴 자체를 경고할 수 있습니다. 이런 경우에는 초기 상태를 활용하거나, 실제 프로젝트에서는 React Query, SWR, Router loader 또는 Suspense 기반의 데이터 패칭 방식을 사용하는 것이 더 권장됩니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

useEffect return문

0

44

3

할 일 수정 질문

0

39

2

컴포넌트 분리하기 강의 편

0

45

2

몽고디비 접속의 건

0

49

3

소스코드 제공여부

0

61

2

기본 파일 구조

0

54

2

공부방향에 대한 조언

0

72

2

styled-components

0

53

2

상태(State) 가 "시간이 지남~" 에 대해 질문 있습니다.

0

66

2

import {} 중괄호 차이점

0

61

2

[ 문의]몽고DB connect 의 건

0

78

2

제공되는 react_code.zip 중에 ..

0

77

2

커리큘럼 비활성화

0

67

2

설명하시는 개념들을 잘 모르겠습니다.

0

74

2

이해가 절반 정도 되는데요.

0

79

1

styled-components(전역)

0

75

1

cloudinary 관련

0

97

3

useOptimistic 실전-1 useState

0

102

2

discord 초대장 갱신이 필요한거같습니다.

0

99

1

할일 관리 앱(메모이제이션)

0

124

2

Web 플랫폼 등록

0

184

2

함수 정의 기준

0

101

2

fetch는 사용되는가

0

102

2

전역상태 관리 선택 기준

0

141

2