useEffect 사용하기

22301 단어 React이걸해냄React

이번엔 useEffect를 사용하는 예시를 씁니다.

useState만으로는 시시각각으로 변하는 데이터들과 컴포넌트들을 관리하기엔 상당히 무리가 있어,
이 부분을 도와주는 useEffect 훅을 사용합니다.

서브 카테고리 목록 불러오기

이전 헤더 컴포넌트에서 서브 카테고리들이 있었던 NavDepth2.js 파일을 봅니다.

import { useState, useEffect } from 'react';
import { MenuLink, ProductLink } from './Links.js';

const NavDepth2 = show => {
  const [pageCategory, setPageCategory] = useState([]);
  const [sub1Category, setSub1Category] = useState([]);

  useEffect(() => {
    fetch('./data/pageCategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setPageCategory(data);
      });
    fetch('./data/sub1CategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setSub1Category(data);
      });
  }, []);

  return (
    <div className={`nav-depth2 ${!show.show ? 'nav-disable' : ''}`}>
      <div className="content-wrap">
        <ul className="nav-depth3">
          {pageCategory.map(list => (
            <MenuLink key={list.id} list={list} />
          ))}
        </ul>

        {sub1Category.map(list => (
          <ProductLink key={list.sub1_id} list={list} />
        ))}
      </div>
    </div>
  );
};

export { NavDepth2 };

01. useState로 데이터 초기값 설정

데이터를 불러오려면,useEffect와 useState는 짝꿍이라고 해도 될 정도로 자주 쓰게 됩니다.
먼저 useState로 카테고리 리스트들을 정의해줍니다.

const [pageCategory, setPageCategory] = useState([]);
const [sub1Category, setSub1Category] = useState([]);


sub2 category가 없는 이유는, 다른 컴포넌트로 들어가서 sub2 category를 불러오기 때문에 여기에는 기술되어 있지 않습니다.

가져올 pageCategoryData.json 목데이터 파일

[
  {
    "id": 1,
    "categoryName": "best",
    "pageUrl": "/products/best"
  },
  {
    "id": 2,
    "categoryName": "new",
    "pageUrl": "/products/new"
  },
  {
    "id": 3,
    "categoryName": "위코뷰 스타일링",
    "pageUrl": "/products/best"
  },
  {
    "id": 4,
    "categoryName": "매장안내",
    "pageUrl": "/products/best"
  }
]

page category는 이렇게 이름과 url, id 등으로 이루어진 객체들의 조합입니다.
useState 안의 초기값이 빈 배열로 되어있기 때문에 여러 개의 카테고리 오브젝트를 불러올 겁니다.

02. useEffect로 비동기 함수 만들기

useEffect(() => {
    fetch('./data/pageCategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setPageCategory(data);
      });
    fetch('./data/sub1CategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setSub1Category(data);
      });
  }, []);

줄이 굉장히 길어서 좀 어지러워 보이지만, 기본적인 구조는 이렇습니다.

useEffect(함수,추적할 요소);
useEffect(()=>{},[]);

여기서는 추적할 요소가 []이렇게 빈 배열이므로 데이터들을 불러오는 행위는 1번만 실행됩니다.

//만약에
useEffect(() => {
    fetch('./data/pageCategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setPageCategory(data);
      });
    fetch('./data/sub1CategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setSub1Category(data);
      });
  }); //이렇게 빈 배열이 없어진다면....

데이터는 무한로딩이 됩니다.
이제 안쪽의 fetch 함수를 살펴보면

//이런 구조
fetch().then().then();

fetch('./data/pageCategoryData.json', { method: 'GET' })
1. 먼저 fetch 로 지정해준 경로의 json 파일을 'GET'메소드로 불러옵니다.
.then(res => res.json())
2. response로 이 데이터를 json화 시켜줍니다.(이미 json으로 작성했지만 안전하게 한번 더)
.then(data => {setPageCategory(data);});
3. 이렇게 받은 json 데이터는 setPageCategory 함수로 인해 해당 데이터로 갱신됩니다.
(원래는 초기값에 의해 빈 배열로 아무것도 들어오지 않음)

이제 console로 변수 pageCategory를 출력시키면,

console.log(pageCategory)

처음에는 초기값 빈 배열 []만 출력됩니다.
하지만 데이터를 끌고오고 나서는,배열 안에 json 내용들이 그대로 들어오는 것을 확인할 수 있습니다.

이제 이 데이터들을 어떻게 리스트로 쪼개서 나눠줘야 하죠?

03. map함수로 리스트를 생성하기

<ul className="nav-depth3">
          {pageCategory.map(list => (//pageCategory의 내용을 list라는 인자로 받습니다.
            <MenuLink key={list.id} list={list} />
            //pageCategory의 객체 갯수만큼 MenuLink 컴포넌트를 리턴합니다.
          ))}
</ul>

nav-depth3라는 클래스를 가진 ul이 있습니다.
그리고 그 안에서 함수가 하나 실행될텐데, 바로 불러온 pageCategory의 배열을 이용합니다.
아까 pageCategory는 객체로 이루어진 하나의 배열이었죠?
이제 map 함수를 통해 배열의 하나하나마다 콜백함수를 실행해줄텐데,
바로 MenuLink라는 컴포넌트를 리턴하는 함수입니다.
저 위에 console.log(list)를 추가하면 pageCategory의 데이터가 출력되는 것을 확인할 수 있습니다.
또한 list={list}처럼, 데이터를 그대로 자식 컴포넌트에게 넘겨줄 수도 있습니다.

MenuLink 컴포넌트를 뜯으면

function MenuLink({ list }) {
  return (
    <li>
      <Link to={list.pageUrl}>{list.categoryName}</Link>
    </li>
  );
}

인자로 물려받은 list에서 pageUrl과 categoryName까지 끌어와 출력합니다!
sub2 category도 이런 방식으로 렌더링시켜주어 구현했습니다.

마무리

간단한 메뉴 구현을 통해 useEffect가 어떻게 굴러가고, 데이터를 어떻게 전달하는지 배웠습니다.
이외에도 useEffect는 데이터를 불러오는것뿐 아니라 사이드 이펙트를 관리하는데에 쓰인다는데, 다른 케이스는 제가 적용해보지 않아 모르지만, 어떻게 사용되는지 궁금하네요!

좋은 웹페이지 즐겨찾기