상태관리

지렁·2024년 3월 23일

직업 종류를 보여주는 api가 존재한다
/api/v1/job-categories 해당 api를 호출하면 현재 저장되어 있는 job 종류를 아래와 같은 배열 형태를 불러올 수 있다

{
    "data": {
        "jobGroupList": [
            {
                "id": 1,
                "name": "개발",
                "jobCategoryList": [
                    {
                        "id": 2,
                        "name": "서버개발자"
                    },
                    {
                        "id": 3,
                        "name": "프론트엔드개발자"
                    }
                ]
            }
        ]
    }
}

이걸 어디다가 적용해야하는지?

  • 회원가입 절차
  • 커피챗 카드
  • 커피챗 디테일
  • 마이페이지

사용되는 곳이 이렇게 많다

첫번째 시도

recoil로 상태 저장을 하자

main페이지 첫 진입 시에 한번 호출하여 recoil로 상태관리 하는 방법을 시도했었다

하지만 값이 초기화되는 문제가 발생했다

그래서 매 컴포넌트마다 값을 저장할 수 있는 state 을 만들어야했다 .. 중복 코드가 많기에 이 방법은 마음에 들지 않았다

두번째 시도

훅으로 만들자

이렇게 훅에서 한번만 값을 저장할 수 있도록 직업데이터를 불러오는 hook을 만들었다

그리고 필요한 곳에서 이 훅을 호출하였고 jobCategories을 prop으로 내려주는 방식으로 사용하였다

const useFetchJobCategories = () => {
  const [jobCategories, setJobCategories] = useRecoilState(kindOfJdState);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchJobCategories = async () => {
      setLoading(true);
      try {
        const { jobGroupList } = await getJobCategory();
        setJobCategories(jobGroupList[0].jobCategoryList);
        localStorage.setItem('jobCategories', JSON.stringify(jobGroupList[0].jobCategoryList));
        setError(null);
      } catch (error) {
        setError(error);
        setJobCategories([]);
      } finally {
        setLoading(false);
      }
    };
    fetchJobCategories();

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return { jobCategories, loading, error, setJobCategories };
};

export default useFetchJobCategories;

문제

필요한 곳에서 이 훅을 호출하면 결국 api 가 재요청되어서 결국 불필요한 api 요청이 생겨버린다

같은 데이터를 사용하기 위하여 사용하는 곳에서 항상 api 를 호출해야할까 싶은 고민이 있었다

그래서 다른 방법을 찾아보게 되었다

세번째 시도

App.jsx 에서 한번 호출하고 localStorage에 직업 정보 값을 저장해놓자!

이 방법이 좋았던 이유가 첫번째로 새로고침 시에도 localStorage는 유지가 되는 점, 두번째로 api호출을 최상위컴포넌트에서 딱 1번만 해도 된다는 점이었다

그래서 아래와 같이 App 컴포넌트에서 useFetchJobCategories을 호출하였다

function App() {
  useAuth();
  useFetchJobCategories();

호출하면 이렇게 로컬스토리지에 jobCategories 라는 키값으로 저장을 하게 되고 필요한 곳에서 getItem 해서 사용하면 된다!!

import { useEffect, useState } from 'react';

import { getJobCategory } from 'api/api';
import { useRecoilState } from 'recoil';
import { kindOfJdState } from 'recoil/atoms';

const useFetchJobCategories = () => {
  const [jobCategories, setJobCategories] = useRecoilState(kindOfJdState);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchJobCategories = async () => {
      setLoading(true);
      try {
        const { jobGroupList } = await getJobCategory();
        setJobCategories(jobGroupList[0].jobCategoryList);
        localStorage.setItem('jobCategories', JSON.stringify(jobGroupList[0].jobCategoryList));
        setError(null);
      } catch (error) {
        setError(error);
        setJobCategories([]);
      } finally {
        setLoading(false);
      }
    };
    fetchJobCategories();

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return { jobCategories, loading, error, setJobCategories };
};

export default useFetchJobCategories;

profile
공부 기록 공간 🎈💻

0개의 댓글