[React] custom hook관련 경고 메세지

Hwanhoon KIM·2023년 7월 30일
0

에러

커스텀 훅으로 json-server에 있는 데이터를 가져오려는데 이 훅을 컴포넌트에 쓰면 다음과 같은 에러가 발생한다.

VM132648:1 Warning: Cannot update a component (TodoList) while rendering a different component (TodoList). To locate the bad setState() call inside TodoList, ...

훅 코드

훅 코드는 다음과 같다.

import { useEffect, useState } from 'react';
import { T_todoState, fetchTodo } from '../redux/modules/todo';
import { useAppDispatch } from '../redux/config/configStore';
import { getTodoDB } from '../axios/dbApi';

const useFetchTodoDB = (): void => {
  const [todoDB, setTodoDB] = useState<T_todoState>([]);
  const dispatch = useAppDispatch();

  useEffect(() => {
    const getData = async (): Promise<void> => {
      try {
        const db = await getTodoDB();
        setTodoDB(db.data.database.todo);
      } catch (error) {
        console.log(error);
      }
    };
    getData();
  }, []);

  if (todoDB.length > 0) {
    dispatch(fetchTodo(todoDB));
  }

  return;
};

export default useFetchTodoDB;

이유

이 경고는 useFetchTodoDB 훅에서 상태 업데이트를 수행하는 동안 컴포넌트 렌더링이 진행되어 생기는 문제다.
useEffect 훅은 컴포넌트가 렌더링된 이후에 비동기적으로 데이터를 가져오는데 사용되는 것이 좋다.
그러나 useFetchTodoDB 훅은 렌더링 시에 상태 업데이트를 수행하고 있기 때문에 경고가 발생하는 것이다.

렌더링 중에 상태를 업데이트하는 것은 React에서 권장되지 않는 방식이므로, 이런 상황에서는 아래와 같이 useEffect를 사용하여 상태 업데이트를 따로 처리하자.

해결

useEffect를 사용하여 코드를 작성하면 해당 경고가 사라진다.

const useFetchTodoDB = (): void => {
  (코드 생략)...
  
  useEffect(() => {
    if (todoDB.length > 0) {
      dispatch(fetchTodo(todoDB));
    }
  }, [todoDB, dispatch]);

  return;
};

export default useFetchTodoDB;

useEffect는 비동기 함수가 아닌데도 불구하고, 해당 에러가 사라지는 중요한 이유는 react에서 useEffect는 모든 컴포넌트들이 렌더링이 완료된 후에 실행되는 함수이기 때문이다.

profile
Fullstack Developer, I post about HTML, CSS(SASS, LESS), JavaScript, React, Next, TypeScript.

0개의 댓글