til

Next.js입문 3일 차 @zustand

fpzmfks 2024. 9. 27. 21:00

오늘은 zustand에서 발목이 잡혀서 한참을 zustand과제를 하는 데에 사용했다. 강의 들으면서 코드를 봤을 때도 느꼈는데, 이전에는 간단했던 zustand가 Next.js로 오면서 많이 어려워진 것 같다. 특히 type script로 값의 타입을 설정해두어야 한다는 것이 너무 큰 난관이었다. 

 

아래는 우여곡절 끝에 완성한 zustand store 코드이다. 보다시피 타입 선언만 3번을 하고, 처음쓰는 주제에 이렇게 선언한 타입을 어떻게 줄일 수 없을까하다가 크게 코드가 꼬여서 튜터님의 안내를 받아 type 정리를 다시 할 수 있었다. 

export interface CountProps {
  count: number;
}
export interface CountState extends CountProps {
  plusCount: () => void;
  minusCount: () => void;
  resetCount: () => void;
}

export type CountStore = ReturnType<typeof createCountStore>;

export const createCountStore = (initProps: Partial<CountProps>) => {
  const DEFAULT_PROPS: CountProps = {
    count: 0,
  };
  return createStore<CountState>()((set) => ({
    ...DEFAULT_PROPS,
    ...initProps,
    plusCount: () => set((state) => ({ count: state.count + 1 })),
    minusCount: () => set((state) => ({ count: state.count - 1 })),
    resetCount: () => set((state) => ({ ...initProps })),
  }));
};

 

 

또 보면 CountStore라는 처음보는 형태의 구조를 가진 타입은 이 코드 내에서 쓰이지 않는데, 이건 여기서 만든 함수(createCountStore)의 결과값의 타입을 ZustandProvider에서 가져가서 사용할 수 있도록 하는 것이다. 

 

아래 코드를 보면

const storeRef = useRef<CountStore>()

라는 곳에서 <CountStore>라는 타입을 가져와서 사용하는 데 이는 이후에 

storeRef.current = createCountStore(props)

에서 함수(createCountStore)를 가져다가 쓰기 때문이다.

"use client";

import { CountState, CountStore, createCountStore } from "@/countStore";
import React, { useContext, useRef } from "react";
import { createContext } from "react";
import { useStore } from "zustand";

export const CountContext = createContext<CountStore | null>(null);

export function useCountContext<T>(selector: (state: CountState) => T): T {
  const store = useContext(CountContext);
  if (!store) throw new Error("Missing CountContext.Provider in the tree");
  return useStore(store, selector);
}

export function CountProvider({
  children,
  ...props
}: React.PropsWithChildren<{ count: number }>) {
  const storeRef = useRef<CountStore>();

  if (!storeRef.current) {
    storeRef.current = createCountStore(props);
  }

  return (
    <CountContext.Provider value={storeRef.current}>
      {children}
    </CountContext.Provider>
  );
}

 

이외에도 DEFAULT_PROPS와 initProps가 무엇인지에 대한 인식이나 아래 부분의 CountState 타입에 CountProps 타입이 포함되어 있다는 것에 대한 이해 등이 부족해서 과제가 힘들었다. 

export interface CountState extends CountProps {
  plusCount: () => void;
  minusCount: () => void;
  resetCount: () => void;
}

 

아무래도 js 환경에서도 코드리딩 능력이 부족했던 것이, ts 환경에 적응하는 과정에서도 코드리딩이 부족한 결과로 이어진 것 같다. 하지만 결국 어찌저찌 코드리딩에 성공한 것을 보니, 차분하게 살펴보면 못할 것도 없을 것이다. 아무래도 코드리딩 능력을 향상시키기 위해서 다른 사람의 코드를 살펴보거나 하는 등의 과정이 더 필요할 것 같다.