TroubleShooting

[MBTI 테스트] - 왜 함수형 업데이트를 하면 기존의 데이터가 사라지게 될까?

집으로 감자 2025. 2. 23. 00:09

문제 상황

 

처음에는 authStore의 userInfo가 잘 저장되어 있다.

그. 런. 데 테스트를 완료하고 결과 확인하기 버튼을 누르면 userInfo가 사라지는 것을 볼 수 있다.

 

사용자가 테스트를 완료하고 결과 확인하기 버튼을 누를 때 다음과 같은 로직이 작동된다.

💻 기존의 결과 확인하기 버튼 로직

const handleSubmit = async (e) => {
  e.preventDefault();

  const { id, nickname } = userInfo;
  const mbtiResult = calculateMBTI(answers);

  addTestResult.mutate({
    nickname,
    mbtiResult,
    userId: id,
    date: new Date().toLocaleString(KOREAN),
    visibility: false,
  });
  setUserInfo((prev) => ({ ...prev, mbtiResult }));

  navigate(`/my-test-result?mbti=${mbtiResult}`);
};

로직을 잘못 작성한 것 같지는 않아 보이는데..

도대체 뭐가 문제인 것일까?!!?

 

(로직을 잘못 작성한 게 맞았다)

 

 

문제 원인 및 해결 과정

setUserInfo((prev) => ({ ...prev, mbtiResult }));

userInfo가 사라지는 이유는 여기 코드로 인해 발생하는 것이었다.

 

함수형 업데이트로 잘 작성했는데 왜 userInfo가 사라지는 것일까 곰곰이 생각하였다.

setUserInfo는 useState로 생성한 함수가 아니라 useAuthStore(zustand)에서 가져온 함수였다.

✅ useState로 생성한 함수가 아니기 때문에 함수형 업데이트를 사용할 수가 없었다.

이 사실을 깨닫자마자 스스로가 너무 바보처럼 느껴졌다.

 

그렇다면 setUserInfo 안에 원하는 객체 값만 전달해 주면 되는 것일까?

 

💻 기존의 useAuthStore 코드

import { create } from "zustand";
import { persist } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";

const useAuthStore = create(
  persist(
    immer((set) => {
      return {
        accessToken: null,
        setAccessToken: (value) => set({ accessToken: value }),
        isLogin: !!localStorage.getItem("accessToken"),
        setIsLogin: (value) => set({ isLogin: value }),
        userInfo: null,
        setUserInfo: (value) => {
          set({ userInfo: value });
        },
      };
    }),
    {
      name: "authStore",
    }
  )
);

export default useAuthStore;

useAuthStore에서 작성한 코드를 한 번 확인해 보자.

 

setUserInfo: (value) => {
  set({ userInfo: value });
}

현재 setUserInfo의 로직에 수정이 필요한 것을 확인할 수 있다.

🚨 지금 로직은 기존의 값을 덮어쓰는 형식으로 작성되어 있다.

기존의 값에 새로운 값을 추가하는 형식으로 바꿔줘야 원하는 의도한 대로 코드가 돌아갈 수 있다!

 

💻 수정된 useAuthStore 코드

import { create } from "zustand";
import { persist } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";

const useAuthStore = create(
  persist(
    immer((set) => {
      return {
        accessToken: null,
        setAccessToken: (value) => set({ accessToken: value }),
        isLogin: !!localStorage.getItem("accessToken"),
        setIsLogin: (value) => set({ isLogin: value }),
        userInfo: null,
        setUserInfo: (value) => {
          set((state) => {
            state.userInfo = { ...state.userInfo, ...value };
          });
        },
      };
    }),
    {
      name: "authStore",
    }
  )
);

export default useAuthStore;

 

setUserInfo: (value) => {
  set((state) => {
    state.userInfo = { ...state.userInfo, ...value };
  });
},

set 함수에서 이전 값을 가져와 새로운 값을 추가해 주는 로직으로 수정해 주었다!

 

💻 수정된 결과 확인하기 버튼 로직

const handleSubmit = async (e) => {
  e.preventDefault();

  const { id, nickname } = userInfo;
  const mbtiResult = calculateMBTI(answers);

  addTestResult.mutate({
    nickname,
    mbtiResult,
    userId: id,
    date: new Date().toLocaleString(KOREAN),
    visibility: false,
  });
  setUserInfo({ mbtiResult });

  navigate(`/my-test-result?mbti=${mbtiResult}`);
};

 

setUserInfo({ mbtiResult });

이제 setUserInfo에는 새로운 값만 넘겨주면 된다!

 

 

결과

이제 userInfo가 지워지지 않는다.

mbtiResult가 잘 추가되는 것을 확인할 수 있다~!

 

 

반응형