072DATA

zustand에서 state가 undifined.. ( create의 콜백 함수 get(); ) 본문

Anything/오류 해결(error)

zustand에서 state가 undifined.. ( create의 콜백 함수 get(); )

0720 2024. 9. 12. 17:11

오류 파티가 열렸다...

 

 

useContext에서 zustand로 리팩토링 하는 과정에서 나타난 오류인데

로그인 하는 과정에서 분명 token을 set해주었는데도 찾을 수 없다는 오류가 나온다..

const useAuthStore = create((set) => ({
  user: JSON.parse(localStorage.getItem("user")),
  isAuthenticated: !!localStorage.getItem("token"),
  token: null,
  profile: null,
  newNickname: "",

  fetchProfile: async () => {
    try {
      if (token && isAuthenticated) {
        const userData = await getUserProfile(token);
        console.log(userData);
        set({ profile: userData });
      }
    } catch (error) {
      console.log("프로필 정보를 가져오지 못했습니다 : ", error);
    }
  },

  login: async (formData) => {
    const response = await apiLogin(formData);
    console.log(response);
    localStorage.setItem("token", response.accessToken);
    localStorage.setItem("user", JSON.stringify(response));
    set({ isAuthenticated: true, token: response.accessToken, user: response });
    return response;
  },

 

다른 컴포넌트에서 해당 스토어를 임포트해서 token을 console.log로 찍어 보니 

마이페이지만 들어가면 token이 null값으로 나온다ㅠㅠ

 

const MyPage = () => {
  const { isAuthenticated, token, fetchProfile, profile } = useAuthStore();
  const [newNickname, setNewNickname] = useState("");

  useEffect(() => {
    fetchProfile(token);
  }, [isAuthenticated]);

 

MyPage 컴포넌트에서 fetchProfile에게 token값을 전달하는 방식으로 수정해봐도 역시 null..

아무래도 MyPage에서는 token 자체를 못 읽는 것 같다

 

 

근데 로컬 스토리지에는 token이 잘 담겨 있음.. 

 

 에러의 원인을 유추해보니 API 호출까지도 가지 않았고 그냥 token 자체를 읽지 못한 것 같다

왜일까? token은 분명 로그인할 때 업데이트 되고 로컬 스토리지에도 잘 담겨 있다..

zustand에 내가 모르는 무언가가 존재하는 것인가? -> 라고 생각이 들어서 찾아보니

 

 

zustand의 액션 함수 내부에서는 상태를 가져올 때 그냥 가져오지 않고

get()함수를 사용해서 상태를 가져오는 것이었다!

const useAuthStore = create((set, get) => ({
  user: JSON.parse(localStorage.getItem("user")),
  isAuthenticated: !!localStorage.getItem("token"),
  token: null,
  profile: null,
  newNickname: "",

  fetchProfile: async () => {
    try {
      const { token, isAuthenticated } = get();
      if (token && isAuthenticated) {
        const userData = await getUserProfile(token);
        console.log(userData);
        set({ profile: userData });
      }
    } catch (error) {
      console.log("프로필 정보를 가져오지 못했습니다 : ", error);
      throw error;
    }
  },

 

 

create() 함수의 콜백 함수로 set뿐만 아니라 get을 인자로 전달하여

상태를 가져와야하는 함수에서 사용해주니 오류가 해결되는 것이다ㅏㅏㅏ

 

 

 

set과 get을 사용하는 이유

 

너무 궁금해서 zustand에서는 왜 이러한 방식으로 상태를 가져와야 하는지 찾아보았는데

 

상태의 일관성, 액션 함수의 독립성, 리액트의 상태 관리 패턴과의 일관성  등의 이유라고 함

 

상태의 일관성은 쉽게 말해서 함수가 호출되는 시점에서

최신 상태 값을 가져와, 일관된 상태 관리를 한다는 것이고

 

액션 함수의 독립성은 get을 사용하면 다른 액션 함수들이 상태를 변경하더라도,

해당 액션 함수는 최신 상태를 기반으로 동작하게 되어 의존성 문제를 줄일 수 있다는 것

 

리액트의 상태 관리 패턴과의 일관성 같은 경우에는 리액트의 useState같은 훅도

상태를 직접 수정하지 않고 setter 함수를 사용해 상태를 업데이트하는 방식으로 동작하는데

이는 상태가 비동기적으로 업데이트되기 때문임 Zustandgetset도 이와 비슷한 맥락인 것임

 

가장 중요하게는 최신 상태의 값을 가져오는 것이 해당 방식을 사용하는 가장 중요한 이유가 될 것 같음

 

 

마치며..

 

이렇게 오류를 해결하려다 zustand와 한 발 더 친해진 것 같아서 기분이  좋다

강의를 한 두번 듣고 바로 적용해보려고 하다보니 get이라는 방법이 있는지도 몰랐기 때문에..

역시 복습에 복습을 거듭해야지 살아 남을 수 있겠다고 느꼈다.. 내일도 킵고잉!!!!