[๐Ÿ•น๏ธ ํฌ์ผ“๋ชฌ ๋„๊ฐ] useEffect์—์„œ ๋ถˆํ•„์š”ํ•œ ํ˜ธ์ถœ์ด ๋ฐœ์ƒ๋˜๋Š” ์ด์Šˆ

JiEunยท2024๋…„ 1์›” 30์ผ
0

์‹œ์ž‘

ํฌ์ผ“๋ชฌ API๋ฅผ ํ™œ์šฉํ•ด ํฌ์ผ“๋ชฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์žˆ์—ˆ๋‹ค.


๋ฌธ์ œ์  ๋ฐœ์ƒ

๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„์„ ์œ„ํ•ด ๋ทฐํฌํŠธ ๋ฐ”๋‹ฅ์— ๋‹ฟ์„ ๊ฒฝ์šฐ ํฌ์ผ“๋ชฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€๋กœ Get์š”์ฒญ์„ ๋ณด๋‚ด๋„๋ก ํ–ˆ๋‹ค.

const PokeContList = () => {
  const [offset, setOffset] = useState<number>(0);
  const [pokemonList, setPokemonList] = useState<PokeList[]>([]);
  const LIMIT = 20;

  useQuery({
    queryKey: ['pokeList'],
    queryFn: () => upDatePokemon(),
    onSuccess(data) {
      setPokemonList(data);
    },
    onError(err) {
      console.log(err);
    },
  });

  const upDatePokemon = async () => {
    const getPokemonListData = await getPokemonList(LIMIT, offset);
    const nextPokeMonList = getPokemonListData.results;

    setOffset((prevOffset) => (prevOffset = prevOffset + LIMIT));
    setPokemonList((prevList) => [...prevList, ...nextPokeMonList]);

    return nextPokeMonList;
  };

  const eventScroll = () => {
    const { scrollHeight, scrollTop, clientHeight } = document.documentElement;

    if (scrollTop + clientHeight >= scrollHeight) {
      console.log('๋ฐ”๋‹ฅ');
      upDatePokemon();
    }
  };

  useEffect(() => {
    window.addEventListener('scroll', eventScroll);
    console.log('๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ');
    return () => {
      window.removeEventListener('scroll', eventScroll);
    };
  }, [pokemonList]);

  console.log('์นด๋“œ ์ปดํฌ๋„ŒํŠธ๋ฆฌ์ŠคํŠธ');

  return (
    <PokeContainer>
      {pokemonList && pokemonList.map((pokemon) => <PokeInfoCard key={pokemon.name} name={pokemon.name} />)}
    </PokeContainer>
  );
};

export default PokeContList;

๋ณด๋Š”๊ฑฐ์™€ ๊ฐ™์ด ์ฝ˜์†”์ฐฝ์— ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ๊ฐ€ ์—ฌ๋Ÿฌ๋ฒˆ ์ฐํžˆ๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

useEffect๋Š” ํ˜„์žฌ ์˜์กด์„ฑ ๋ฐฐ์—ด๋กœ pokemonList๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
๋”ฐ๋ผ์„œ, ์ฒ˜์Œ ๋ Œ๋”๋ง ๋œ ์ดํ›„ pokemonList์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด useEffect๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

์ดˆ๊ธฐ ํ™”๋ฉด ์ง„์ž… ์‹œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋กœ ๋ถˆ๋Ÿฌ์™€ ์ง€์ง€ ์•Š์œผ๋‹ˆ
๋ทฐํฌํŠธ ๋ฐ”๋‹ฅ์ด ๋ฐ”๋กœ ๋…ธ์ถœ ๋˜๋ฉด์„œ eventScroll ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์–ด ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ˜ธ์ถœ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค ์ƒ๊ฐํ–ˆ๋‹ค.

์ดˆ๋ฐ˜์—๋Š” useEffect์— ์กฐ๊ฑด์„ ๊ฑธ์–ด ๋ดค์ง€๋งŒ
์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜์ง€ ์•Š์•„ ๋ฌดํ•œ ์Šคํฌ๋กค์ด ์‹คํ–‰๋˜์ง€ ์•Š์•˜๋‹ค.


๐Ÿ› ๏ธ ์Šค์ผˆ๋ ˆํ†ค์„ ์ถ”๊ฐ€ํ•ด ๋ณด์ž.

์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜์ง€? ๋ผ๋Š” ์ƒ๊ฐ์œผ๋กœ ํ•œ์ฐธ ๊ณ ๋ฏผํ•˜๋˜ ์ค‘ ์Šค์ผˆ๋ ˆํ†ค์„ ์ƒ๊ฐํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

์Šค์ผˆ๋ ˆํ†ค=๋ผˆ๋Œ€

ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ ๊ฐ€ ์™„์ „ํžˆ ๋ Œ๋”๋ง๋˜๊ธฐ ์ „์— ๋‚˜ํƒ€๋‚˜๋Š” ํ™”๋ฉด, ์ตœ์ข… ์ฝ˜ํ…์ธ ๊ฐ€ ์ œ์ž๋ฆฌ์— ๋กœ๋“œ๋˜๊ธฐ ์ „์— ํŽ˜์ด์ง€ ๊ตฌ์กฐ์˜ ์œค๊ณฝ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์—ฐํ•œ ์ƒ‰์ƒ์˜ ๋ฐฐ๊ฒฝ, ์„  ๋ฐ ํ…์ŠคํŠธ๋กœ ๊ตฌ์„ฑ
[React] ์Šค์ผˆ๋ ˆํ†ค ๋กœ๋”ฉ์ด๋ž€? - by07a๋‹˜

๋งํ•˜์ž๋ฉด ๋‚ด๊ฐ€ ๋ณด์—ฌ์ฃผ๋ ค๊ณ  ํ•˜๋Š” ์ปจํ…์ธ ์™€ ๋™์ผํ•œ ์‚ฌ์ด์ฆˆ๋กœ ๋งŒ๋“ค์–ด์ง„ ํšŒ์ƒ‰ ์ปจํฌ๋„ŒํŠธ๋ฅผ ๋ฐ์ดํ„ฐ๊ฐ€ ๋กœ๋”ฉ ๋  ๋•Œ ๊นŒ์ง€ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

import styled, { keyframes } from 'styled-components';

const load = keyframes`
  100% {
    background-position: -100% 0;
  }
`;

const SkeletonWrap = styled.div`
  position: relative;
  overflow: hidden;
  border-radius: 10px;
  background: linear-gradient(90deg, #e5e5e5 30%, #f0f0f0 30%, #f0f0f0 30%, #e5e5e5 50%);
  background-size: 200% 100%;
  background-position: 100% 0;
  animation: ${load} 1.5s infinite;
  /* box-shadow: 4px 4px 20px 0 rgba(0, 0, 0, 0.1); */
  padding: 20px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  z-index: 1;
  cursor: pointer;
  transition: 0.3s;
  width: 100%;
  height: 0;
  padding-bottom: 100%;
  background-color: #ccc;
`;

const SkeletonCard = () => {
  return (
    <>
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
      <SkeletonWrap />
    </>
  );
};

export default SkeletonCard;

์ ์€ ๊ฐฏ์ˆ˜๋กœ ๊ตฌ์„ฑํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ
๋ทฐํฌํŠธ ๋ฐ”๋‹ฅ์ด ๊ณ„์† ๋‹ฟ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ด 12๊ฐœ์˜ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ฐฐ์น˜ํ–ˆ๋‹ค.

์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋Š” ๊ตฌ๊ธ€๋ง์„ ํ†ตํ•ด ๊ฐ€์ ธ์™€ ์ƒ‰์ƒ ๋ฐฐ์น˜๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•ด ์ˆ˜์ •ํ–ˆ๋‹ค.


๐Ÿฅน ๋ฌดํ•œ ์Šคํฌ๋กค ๊ฐ์ง€์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ์˜€๋‹ค...?

๊ทธ๋Ÿฌ๊ณ  ๋‹ค์‹œ ์ฝ˜์†”์ฐฝ์„ ํ™•์ธํ•ด ๋ดค๋Š”๋ฐ ๋™์ผํ•˜๊ฒŒ ๋‚˜์™”๋‹ค...

๋ทฐํฌํŠธ๊ฐ€ ๋ฐ”๋‹ฅ์— ๋‹ฟ๊ธฐ ์ „์— ์Šค์ผˆ๋ ˆํ†ค์„ ๋ณด์ด๊ฒŒ ํ–ˆ์ง€๋งŒ ๊ทธ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ์—ˆ๋˜ ๊ฒƒ ๊ฐ™์•„
useEffect ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•ด ๋ณด์ž.

  const [offset, setOffset] = useState<number>(0);
  const [pokemonList, setPokemonList] = useState<PokeList[]>([]);
  const LIMIT = 20;

  useQuery({
    queryKey: ['pokeList'],
    queryFn: () => upDatePokemon(),
    onSuccess(data) {
      setPokemonList(data);
      console.log('useQuery ์‹คํ–‰');
    },
    onError(err) {
      console.log(err);
    },
  });

  const upDatePokemon = async () => {
    const getPokemonListData = await getPokemonList(LIMIT, offset);
    const nextPokeMonList = getPokemonListData.results;

    setOffset((prevOffset) => (prevOffset = prevOffset + LIMIT));
    setPokemonList((prevList) => [...prevList, ...nextPokeMonList]);
    console.log('upDatePokemon ์‹คํ–‰');

    return nextPokeMonList;
  };

  const eventScroll = () => {
    const { scrollHeight, scrollTop, clientHeight } = document.documentElement;

    if (scrollTop + clientHeight >= scrollHeight) {
      console.log('๋ฐ”๋‹ฅ๊ฐ์ง€ ์—…๋ฐ์ดํŠธ');
      upDatePokemon();
    }
  };

  useEffect(() => {
    window.addEventListener('scroll', eventScroll);
    console.log('๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ');
    return () => {
      window.removeEventListener('scroll', eventScroll);
    };
  }, [pokemonList]);

  console.log('์นด๋“œ ์ปดํฌ๋„ŒํŠธ๋ฆฌ์ŠคํŠธ', pokemonList);

๊ฐ๊ฐ์˜ ๊ตฌ๊ฐ„์— console.log๋ฅผ ์ถ”๊ฐ€ํ•ด ํ™•์ธํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

๐Ÿ”Ž ๋ฌธ์ œ์  ๋ฐœ๊ฒฌ!

useEffect์˜ ์˜์กด์„ฑ ๋ฐฐ์—ด์— ์ถ”๊ฐ€๋˜์–ด ์žˆ๋Š” pokemonList์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝํ•˜๋ฉด useEffect ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
์ฒ˜์Œ์—๋Š” pokemonList๊ฐ€ ๋นˆ๋ฐฐ์—ด๋กœ ์‹œ์ž‘ ๋˜๋Š”๋ฐ ์—ฌ๊ธฐ์„œ useEffect๊ฐ€ ๋‘๋ฒˆ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

useQuery๋ฅผ ํ†ตํ•ด upDatePokemon()์ด ์‹คํ–‰๋˜๊ณ  pokemoList์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ค๊ฒŒ ๋œ๋‹ค.
์—ฌ๊ธฐ์„œ ์„ธ๋ฒˆ์งธ useEffect๊ฐ€ ์‹คํ–‰ ๋˜๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค.

์ฆ‰, pokemonList๊ฐ€ ๋นˆ๋ฐฐ์—ด์ผ ๊ฒฝ์šฐ์—๋Š” useEffect๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก ํ•ด์•ผํ•œ๋‹ค.


๐Ÿฅน ํ•ด๊ฒฐ!

useEffect(() => {
  if (pokemonList.length > 0) {
    window.addEventListener('scroll', eventScroll);
    console.log('๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ');
    return () => {
      window.removeEventListener('scroll', eventScroll);
    };
  }
}, [pokemonList]);

์ง๊ด€์ ์œผ๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๊ฒŒ pokemonList๋ฐฐ์—ด์˜ ๊ธธ์ด๊ฐ€ 0๋ณด๋‹ค ํด ๊ฒฝ์šฐ useEffect ๋‚ด๋ถ€ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰ํ•˜๊ฒŒ ์กฐ๊ฑด๋ฌธ์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

๋‹ค์‹œ ์ฝ˜์†”์ฐฝ์„ ํ™•์ธํ•˜๋‹ˆ useEffect๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋‘๋ฒˆ ์‹คํ–‰๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค...!

๐Ÿ› ๏ธ ๋ฆฌํŒฉํ† ๋ง

useEffect(() => {
    const eventScroll = () => {
      const { scrollHeight, scrollTop, clientHeight } = document.documentElement;

      if (scrollTop + clientHeight >= scrollHeight) {
        console.log('๋ฐ”๋‹ฅ๊ฐ์ง€ ์—…๋ฐ์ดํŠธ');
        upDatePokemon();
      }
      console.log('๋ฐ”๋‹ฅ๊ฐ์ง€ ์‹คํ–‰');
    };

    if (pokemonList.length > 0) {
      window.addEventListener('scroll', eventScroll);
      console.log('๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ');
      return () => {
        window.removeEventListener('scroll', eventScroll);
      };
    }
  }, [pokemonList]);

๊ทธ๋ฆฌ๊ณ  eventScroll๋Š” pokenomList์˜ ๋ฐฐ์—ด ๊ธธ์ด๊ฐ€ 0์ด์ƒ์ธ ๊ฒฝ์šฐ, ์Šคํฌ๋กค์ด ๋ฐ”๋‹ฅ์— ๋‹ฟ์„ ๊ฒฝ์šฐ์—๋งŒ ์‹คํ–‰๋˜๊ธฐ์— useEffect ๋‚ด๋ถ€์— ๊ฐ™์ด ๋ฌถ์–ด ์ฃผ์—ˆ๋‹ค.


๋งˆ์น˜๋ฉฐ

์ด๋ฒˆ ์‹œ๊ฐ„์„ ํ†ตํ•ด console.log๋ฅผ ์ž˜ ํ™œ์šฉํ•ด ๋ฌธ์ œ๋ฅผ ํŒŒ์•…ํ•˜์ž๋Š” ์ ,
useEffect๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์กฐ๊ฑด๋ฌธ์ด๋‚˜ ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์ถ”๊ฐ€ํ•ด ์ฃผ๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•˜๋ฉด์„œ ์‚ฌ์šฉํ•ด์•ผ ๊ฒ ๋‹ค๋Š” ๊ตํ›ˆ์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

profile
๐Ÿ’ป ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋ชฉํ‘œ๋กœ ์„ฑ์žฅ ์ค‘! (์•Œ์•„๋ดค๋˜ ๋‚ด์šฉ ๋“ฑ์„ ์ •๋ฆฌํ•˜๊ธฐ)

0๊ฐœ์˜ ๋Œ“๊ธ€