프로젝트

Rendered more hooks than during the previous render.

ejunyang 2024. 6. 17. 18:42

👾 오ㅗ류

지출내역리스트 코드를 작성하다 마주한 에러이다. 한참 고민하다가 if문 구문 순서를 바꾸어 보았다.

const ExesList = () => {
  const { selectedMonth } = useContext(ExpenseContext);
  const { userInfo } = useContext(AuthContext);

  const {
    data: expenses = [],
    isPending,
    error,
  } = useQuery({
    queryKey: ["expenses"],
    queryFn: getExpense,
  });

  const filteredExpenses = userInfo
    ? expenses.filter(
        (exe) => exe.month === selectedMonth && exe.user === userInfo.id
      )
    : [];

  const totalAmount =
    filteredExpenses && filteredExpenses.length > 0
      ? filteredExpenses.reduce((acc, cur) => {
          return (acc += cur.amount);
        }, 0)
      : 0;
      
      
  if (isPending) {
    return <div>로딩중입니다.</div>;
  }

  if (error) {
    return <div>데이터를 불러오지 못했습니다.</div>;
  }


  return (
    <div>
      <TotalTitle>
        {`${selectedMonth + 1}월`} 한 달 동안
        <strong>총 {totalAmount}원</strong>
        사용했어요.
      </TotalTitle>
      <ul>
        {filteredExpenses &&
          filteredExpenses.map((exe) => {
            return <ExesItem key={exe.id} exe={exe} />;
          })}
      </ul>
    </div>
  );
};

export default ExesList;

 

 

 

 

💡 해결

const ExesList = () => {
  const { selectedMonth } = useContext(ExpenseContext);
  const { userInfo } = useContext(AuthContext);

  const {
    data: expenses = [],
    isPending,
    error,
  } = useQuery({
    queryKey: ["expenses"],
    queryFn: getExpense,
  });

  const filteredExpenses = userInfo
    ? expenses.filter(
        (exe) => exe.month === selectedMonth && exe.user === userInfo.id
      )
    : [];

  if (isPending) {
    return <div>로딩중입니다.</div>;
  }

  if (error) {
    return <div>데이터를 불러오지 못했습니다.</div>;
  }

  const totalAmount =
    filteredExpenses && filteredExpenses.length > 0
      ? filteredExpenses.reduce((acc, cur) => {
          return (acc += cur.amount);
        }, 0)
      : 0;

 

이렇게 위치를 바꾸니까 해결됐다. 코드의 흐름을 보니 이 때 expenses 데이터가 아직 로딩되지 않았거나 에러가 발생했다면, filteredExpenses의 계산 과정에서 문제가 발생했던 것.  isPending 및 error 체크를 먼저 수행하도록 변경하면 데이터 로딩 상태와 에러 상태를 먼저 확인하고, 해당 상태에 맞는 UI를 렌더링할 수 있다.

 

따라서 isPending 및 error 체크 구문의 위치를 변경함으로써, 데이터 로딩 상태와 에러 상태를 먼저 확인하고 그에 따른 적절한 UI를 렌더링할 수 있게 되었다. 코드의 안정성과 사용성을 높이는 데 도움이 되는 것 같다!