React - loading state

정지현·2024년 5월 15일

React

목록 보기
3/8
post-thumbnail

저번 아티클을 번역하면서 간단한 get 요청이지만 어떻게 UI적으로 신경쓸 수 있는 구성을 만들 수 있는지 확인해 보았었다.

해당 코드로 만들어낼 수 있는 화면은 다음과 같다.

'use client';

import Image from 'next/image';
import Skeleton from 'react-loading-skeleton';
import '../styles/index.css';
import 'react-loading-skeleton/dist/skeleton.css';

import { PokeDataType } from '../types';

const PokemonCard = ({
  isLoading,
  error,
  data,
}: {
  isLoading: boolean;
  error: any;
  data: PokeDataType;
}) => {
  if (isLoading) {
    return (
      <article className="card">
        <figure>
          <Skeleton
            baseColor="gray"
            circle
            enableAnimation
            width={200}
            height={200}
          />
          <figcaption>
            <Skeleton
              baseColor="gray"
              enableAnimation
              height={21}
              width={109}
            />
            <Skeleton
              baseColor="gray"
              enableAnimation
              height={21}
              width={109}
            />
          </figcaption>
        </figure>
      </article>
    );
  }

  if (error) {
    return (
      <article className="card">
        <figure>
          <Image
            width={200}
            height={200}
            src="https://ui.dev/images/courses/pokemon-unknown.png"
            alt="pokemon error"
          />
          <figcaption>
            <h4>Oops.</h4>
            <h6>{error}</h6>
          </figcaption>
        </figure>
      </article>
    );
  }
  return (
    <article className="card">
      <figure className="">
        {data?.sprites?.front_default && (
          <Image
            width={200}
            height={200}
            src={data?.sprites?.front_default}
            alt={data.name}
          />
        )}
        <figcaption>
          <h4>{data.name}</h4>
          <h6>No. {data.id}</h6>
        </figcaption>
      </figure>
    </article>
  );
};

export default PokemonCard;

여전히 무언가 아쉬운 점이 보인다.

일부러 개발자 콘솔로 인터넷 속도에 제약을 걸고 본다면 이미지 하나 당 2초 정도가 걸리는 것을 확인할 수 있다.

그리고 스크린샷으로 찍지는 못했지만, 사용량이 오버될때 페칭이 실패해 alt가 뜨는 모습도 확인할 수 있었다.

이번에 react-loading-skeleton으로 간편하게 컴포넌트의 로딩을 만들어내긴 했지만, 이미지 역시 비동기 콜이기 때문에 이 부분을 잡아주면 조금 더 괜찮은 UI가 될 거라고 생각한다.

// components/PokemonImage.tsx
'use client';

import React from 'react';
import Image from 'next/image';

type Props = {
  front_default: string;
  name: string;
};

const PokemonImage: FC<Props> = ({ front_default, name }) => {
  const [src, setSrc] = React.useState(front_default);

  return (
    <Image
      src={src}
      width={200}
      height={200}
      onError={() =>
        setSrc('https://ui.dev/images/courses/pokemon-unknown.png')
      }
      alt={name}
    />
  );
};

export default PokemonImage;

페칭에 실패하는 경우는 쉽게 에러 이미지를 가져오도록 처리할 수 있었지만, 로딩의 경우는 조금 까다로운 것 같다.

사실 이번에 적용한 스켈레톤뷰의 경우 리액트 컴포넌트이기 때문에, 대체해주려면 svg를 사용해야 한다! 물론 넥스트의 Image 에 대한 이해가 부족해서 그런걸 수도 있겠지만...

이 부분에 대해서는 조금 더 나은 레퍼런스를 찾아보는 것이 좋겠다.

profile
Can an old dog learn new tricks?

0개의 댓글