인프런 커뮤니티 질문&답변

루룸님의 프로필 이미지

작성한 질문수

Slack 클론 코딩[실시간 채팅 with React]

swr 사용하기(쿠키 공유하기)

fetcher 함수의 data 값이 두번 찍히는 이유

24.07.24 00:02 작성

·

94

·

수정됨

0

Login.tsx에서 swr로 호출한 users의 data 값을 return 직전에 console 로그로 찍어봤는데요

네트워크 탭에서는 users 요청은 한번 밖에 없었는데
undefined와 false가 연달아서 찍히더라구요

다른 질문에서 답변해주신 내용을 보니 데이터 로딩중엔 undefined라고 말씀해주셨는데, 맨 처음 컴포넌트가 렌더링될 때 useSWR이 api를 호출하게 되고 이때 console.log(data)는 아직 데이터가 로딩 중이라서 undefined가 찍히게 되고, 이후 데이터 로딩이 완료되면 useSWR이 다시 호출되어? false가 찍히는 프로세스로 이해했는데 맞는걸까요

그렇다면 useSWR로 api호출 시 무조건 최소 2번 렌더링될 수 밖에 없는걸까요?

image.png

// Login.tsx
import React, { useState, useCallback, useEffect } from 'react';
import { TextField, Button } from '@components/index';
import { Link, Navigate } from 'react-router-dom';
import { useInput } from '@hooks/useInput';
import { LogoSlack } from '@assets/icons/';
import axios from 'axios';
import useSWR from 'swr';
import fetcher from '@utils/fetcher';

const Login = () => {
  // useSWR은 get으로 요청한 데이터를 받아와서 저장한다.
  // mutate : 내가 원할 때 SWR 호출하기
  const { data, error, mutate } = useSWR('http://localhost:3095/api/users', fetcher, {
    dedupingInterval: 5000, // 주기적으로 호출하지만, dedupingInterval 기간 내에는 캐시에서 불러온다
  });
  const [logInError, setLogInError] = useState(false);
  const [email, setEmail, onChangeEmail] = useInput('');
  const [password, setPassword] = useInput<string>('');

  const onChangePassword = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setPassword(e.target.value);
    },
    [email, password, data],
  );

  const onSubmit = useCallback(
    (e) => {
      setLogInError(false);
      axios
        .post(
          'http://localhost:3095/api/users/login',
          { email, password },
          {
            withCredentials: true,
          },
        )
        .then(() => {
          mutate();
        })
        .catch((error) => {
          setLogInError(error.response?.status === 401);
        });
    },
    [email, password],
  );

  console.log(data); // 

  if (data) return <Navigate to="/workspace/channel" />;

  return (
    <div className="max-w-[400px] mx-auto px-[20px]">
      <h1 className="flex justify-center pt-[60px] pb-[20px]">
        <LogoSlack />
        <span className="blind">Slack</span>
      </h1>
      <TextField label="이메일 주소" type="email" value={email} onChange={onChangeEmail} />
      <TextField label="비밀번호" type="password" value={password} onChange={onChangePassword} />
      {logInError && <p className="mb-[20px] mt-[-10px] text-red-500 font-normal">로그인 실패</p>}
      <Button text="로그인" onClick={onSubmit} />
      <p className="mt-[10px] text-center">
        Slack을 처음 사용하시나요?
        <Link to="/sign" className="ml-[4px] text-blue-600">
          회원가입
        </Link>
      </p>
    </div>
  );
};

export default Login;

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

2024. 07. 24. 00:31

네 맞습니다. 적어도 로딩중->로딩완료를 구분하기 위해서라도 두 번 렌더링될 수밖에 없습니다.

루룸님의 프로필 이미지

작성한 질문수

질문하기