sihyun10 / FE_PS_Final_Refactor

몰리턴 기업 연계 프로젝트 코드리뷰 및 리팩토링
0 stars 0 forks source link

전역 상태 관리에 대해 코드 리뷰하기 #13

Closed 05Castle closed 1 year ago

05Castle commented 1 year ago

데이터를 받아서 전역 상태로 관리하고, 다시 컴포넌트로 뿌려주는 데이터의 프로세스를 이해하고 분석하기

분석한 내용, 알게 된 내용은 코멘트로 남기기. 너무 정리할 필요없이 단편적인 코멘트를 여러번 남겨도 좋음!

sihyun10 commented 1 year ago

DataStore.tsx 파일은 zustand 상태 관리 라이브러리를 사용해 전역상태를 관리하는 store를 생성하는 코드이다. zustand 라이브러리에서 제공하는 미들웨어인 persist함수를 활용해 상태를 지속성. 즉, getStorage: () => sessionStorage (세션스토리지)에 저장하고있는 로직이다. persist함수는 기본 옵션localStorage가 사용된다. 하지만 옵션을 세션스토리지로 설정되어있다. 따라서 브라우저 탭을 닫으면 스토리지가 초기화가 됩니다. (참고: localStorage는 데이터 영구저장이 가능함. 사용자가 지우지 않는 이상 계속 브라우저에 남아있다) 이와 관련된 설명은 https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md 이 사이트에 설명되어져있다!

sihyun10 commented 1 year ago

How do I use it with TypeScript

import { create } from 'zustand'
import { persist } from 'zustand/middleware'

interface MyState {
  bears: number
  addABear: () => void
}

export const useBearStore = create<MyState>()(
  persist(
    (set, get) => ({
      bears: 0,
      addABear: () => set({ bears: get().bears + 1 }),
    }),
    {
      name: 'food-storage', // name of item in the storage (must be unique)
      storage: createJSONStorage(() => sessionStorage), // (optional) by default the 'localStorage' is used
      partialize: (state) => ({ bears: state.bears }),
    }
  )
)
sihyun10 commented 1 year ago

image

ResponseItem 인터페이스는 id값과 filename, data 세가지 속성을 가지고 있다. 이미지에 보이는거와 같이 데이터 스토어에 저장되는 개별항목의 형식을 정의한다.

interface DataStoreState {
  responseItems: ResponseItem[];
  addResponseItem: (filename: string, data: string) => number;
  removeResponseItem: (id: number) => void;
}

addResponseItem는 filename과 data를 매개변수로 받아 새로운 ResponseItem을 생성하고, 데이터 스토어에 추가하는 함수를 작성해주었고, removeResponseItem은 주어진 id에 해당하는 ResponseItem을 데이터 스토어에서 제거하는 함수다.

sihyun10 commented 1 year ago

DataStore.tsx파일을 불러와서 사용하고있는 파일들은 8개 파일에서 사용하고 있다. PdfUploadModule>index.tsx, RecentHistory(최근조회내역), PropertyInfo(담보물건요약), PdfSummaryTable1,3(등기부요약), MarketPrice, MarketPriceTable2(시세), Location(입지) 파일이다.

{responseItems.map((item) => (

))}


- **PdfSummaryTable1,3**(등기부요약)
id를 파라미터로 받아오고, useDataStore훅을 사용해, responseItems를 가져온다.
데이터를 저장하고, 해당 데이터를 테이블로 나타낼수있도록 해준다. 또한 responseItems를 가져와 선택된 id에 해당하는 데이터를 찾고, 해당 데이터를 Table 컴포넌트에 전달하여 나타낸다. responseItems 배열 전체를 사용해 필요한 데이터를 가져와 활용하고 있다. (+ 시세파일도 비슷하다)

(예시 코드)
```typescript
const PdfSummaryTable3 = () => {
  const { id } = useParams();
  const { responseItems } = useDataStore();
  const [resData, setResData] = useState();

  useEffect(() => {
    if (!id) {
      console.log('URL에 아이디가 제공되지 않았습니다.');
      return;
    }
    const parsedId: number = +id;
    const selectedItem: any = responseItems.find((item) => item.id === parsedId);

    if (selectedItem) {
      setResData(selectedItem.data.rights_other_than_ownership);
    } else {
      console.log(`아이디 ${id}에 해당하는 아이템을 찾을 수 없습니다.`);
    }
  }, [id]);
  • Location(입지) 위의 등기부요약, 시세파일과 로직은 비슷하지만, 조금 다른점은 responseItems 배열에서 id에 해당하는 데이터를 찾아 주소를 추출 후, 위도와 경도를 검색한다. 해당하는 위치를 지도에 표시하고, 관련된 정보는 테이블로 표시하고 있다.
const Location = () => {
  const { id } = useParams();
  const { responseItems } = useDataStore();

  const [address, setAddress] = useState<string>('');
  const [newLat, setLat] = useState<number>(0);
  const [newLng, setLng] = useState<number>(0);
  const link = `https://new.land.naver.com/complexes?ms=${newLat},${newLng},19`;

  useEffect(() => {
    if (!id) {
      console.log('URL에 아이디가 제공되지 않았습니다.');
      return;
    }
    const parsedId: number = +id;
    const selectedItem: any = responseItems.find((item) => item.id === parsedId);

    if (selectedItem) {
      setAddress(selectedItem.data.summary.newAddress);
    } else {
      console.log(`아이디 ${id}에 해당하는 아이템을 찾을 수 없습니다.`);
    }
  }, [id]);

  // 주소 받으면 좌표로 변환해서 전역 상태로 저장
  useEffect(() => {
    const geocoder = new window.kakao.maps.services.Geocoder();
    geocoder.addressSearch(address, (result: any, status: any) => {
      if (status === window.kakao.maps.services.Status.OK) {
        setLat(result[0].y);
        setLng(result[0].x);
      }
    });
  }, [address]);