如何在切换用户配置文件时正确管理 Next.js 项目中的本地存储数据?

问题描述 投票:0回答:1

我正在开发一个 React/Nextjs 应用程序,其中使用自定义 useLocalStorage 挂钩来管理用户配置文件的本地存储。我正在尝试模仿 chatgpt 应用程序。

但是,我遇到了一个问题,即新配置文件的本地存储数据似乎保留了先前配置文件的值,从而导致不正确的行为。

以下是我的应用程序结构的简要描述:

我有不同的用户配置文件。每个配置文件都有自己的密钥,例如:配置文件1-聊天、配置文件2-聊天等。 我正在使用 useLocalStorage 挂钩和基于当前用户配置文件动态生成的密钥。

当用户切换配置文件时,新的配置文件会在应用程序状态中正确设置。

我正在使用提供程序来访问我的应用程序中的这些值。

export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
  const [userProfile, setUserProfile] = useState<ProfileType>(
    UserProfiles.Profile1
  );

  const [chats, setChats] = useLocalStorage(
    `${userProfile.title}-chats`,
    initialState
  );

// ....

这是我用来处理 localStorage 的自定义钩子,经过一些调查后我发现这是在 Nextjs 中执行此操作的方法

// CUSTOM HOOK TO HANDLE LOCAL STORAGE IN NEXTJS
import { useEffect, useState } from "react";

const useLocalStorage = <T>(
  key: string,
  initialState: T
): [T, React.Dispatch<React.SetStateAction<T>>] => {
  const [state, setState] = useState<T>(() => {
    if (typeof window !== "undefined") {
      try {
        const item = localStorage.getItem(key);
        return item ? JSON.parse(item) : initialState;
      } catch (error) {
        console.error("Error parsing local storage data:", error);
      }
    }
    return initialState;
  });

  useEffect(() => {
    if (typeof window !== "undefined") {
      try {
        localStorage.setItem(key, JSON.stringify(state));
      } catch (error) {
        console.error("Error saving data to local storage:", error);
      }
    }
  }, [key, state]);

  return [state, setState];
};

export default useLocalStorage;

这是我更改用户配置文件的组件

const SelectProfileModal = ({
  isOpen,
  onClose,
  onConfirm,
}: SelectProfileModalProps) => {
  const { userProfile, setUserProfile } = useChatContext();
  const router = useRouter();
  const [selectedProfile, setSelectedProfile] =
    useState<ProfileType>(userProfile);

  const handleOnSave = () => {
    setUserProfile(selectedProfile);
    router.push("/");
    onClose();
  };

  return (
    <Modal show={isOpen} onHide={onClose}>
      <ModalHeader closeButton>
        <Modal.Title>Select Profile</Modal.Title>
      </ModalHeader>
      <ModalBody>
        <ListGroup>
          {AvailableProfiles.map((profile) => (
            <ListGroup.Item
              key={profile.id}
              action
              variant="dark"
              onClick={() => setSelectedProfile(profile)}
              active={selectedProfile.id === profile.id}
            >
              {profile.id}- {profile.title}
            </ListGroup.Item>
          ))}
        </ListGroup>
      </ModalBody>
      <ModalFooter>
        <Button variant="secondary" onClick={onClose}>
          Cancel
        </Button>
        <Button variant="primary" onClick={handleOnSave}>
          Select
        </Button>
      </ModalFooter>
    </Modal>
  );
};

我面临的问题是,即使我在应用程序状态下成功切换配置文件,当我切换到不同的配置文件时,本地存储似乎保留了先前配置文件中的数据,从而导致意外行为.

我怀疑该问题可能与用户切换时我为新配置文件初始化本地存储的方式有关。但是,我已经检查了我的代码和 useLocalStorage 挂钩,它们似乎是正确的。

我是 Nextjs 的新人。

我正在寻求有关如何解决此问题的建议。具体来说:

如何确保本地存储针对新配置文件正确初始化?

如果您能提供任何指导或建议来帮助我解决此问题,我将不胜感激。如果您需要查看我的代码的特定部分或其他详细信息,请告诉我。

堆栈:

    "next": "^13.4.12",
    "react": "^18.2.0",

谢谢您的帮助!

预期结果: 我使用 Profile1 问一个问题,它正确存储在 localStorage 的 profile1-chats 键中,然后我切换到 Profile2,localStorage 中的新键应该用空的

[]
初始化。 如果我使用 Profile2 提出问题,它应该存储在相应的本地存储密钥中。

目前结果: 我使用 Profile1 问一个问题,它正确存储在 localStorage 的 profile1-chats 键中,然后切换到 Profile2,localStorage 中的新键已初始化(profile2-chats),但 profile1-chats 的值被复制到 profile2-chats。

reactjs next.js react-hooks local-storage
1个回答
0
投票

我认为,在您提供的代码中,状态初始化仅在安装组件时执行一次,并且取决于作为参数提供的键。如果组件安装后 key 发生变化,状态不会自动更新以响应 key 的变化。

您也可以添加这些代码行吗:

  // Use useEffect to watch for changes in the key
  useEffect(() => {
    if (key) {
      const storedItem = localStorage.getItem(key);
      if (storedItem) {
        try {
          const parsedItem = JSON.parse(storedItem);
          setState(parsedItem);
        } catch (error) {
          console.error("Error parsing local storage data:", error);
        }
      }
    }
  }, [key]);

这是一项艰巨的工作,因此如果出现任何错误,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.