如何使用zustand存储查询结果

Arm*_*man 7 typescript reactjs react-hooks react-query zustand

我想将经过身份验证的用户放入 zustand 商店中。我使用反应查询获取经过身份验证的用户,这会导致一些问题。我不确定我为什么要这样做。我希望与身份验证相关的所有内容都可以在钩子中访问,所以我认为 zustand 是一个不错的选择。

这是获取 auth 用户的钩子:

const getAuthUser = async () => {
  const { data } = await axios.get<AuthUserResponse>(`/auth/me`, {
    withCredentials: true,
  });
  return data.user;
};

export const useAuthUserQuery = () => {
  return useQuery("auth-user", getAuthUser);
};
Run Code Online (Sandbox Code Playgroud)

我想将 auth 用户放入该商店:

export const useAuthStore = create(() => ({
  authUser: useAuthUserQuery(),
}));
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:

错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。出现这种情况可能是由于以下原因之一。

你可以在react文档中阅读它: https://reactjs.org/warnings/invalid-hook-call-warning.html

在此输入图像描述 (为了便于理解,我更改了本文中一些函数的名称。useMeQuery = useAuthUserQuery)

我了解该错误,但我不知道如何修复它。

TkD*_*odo 27

这里的误解是您不需要将反应查询中的数据放入任何其他状态管理解决方案中。React 查询本身就是一个全局状态管理器。你可以这样做:

\n

const { data } = useAuthUserQuery()

\n

在每个需要数据的组件中。React 查询将自动尝试通过后台重新获取来更新您的数据。如果您的资源不需要\xe2\x80\x99,请考虑设置staleTime.

\n

\xe2\x80\x94-

\n

话虽如此,如果您确实想将react-query中的数据放入zustand中,请在zustand中创建一个setter并在查询的onSuccess回调中调用它:

\n
useQuery(key, queryFn, { onSuccess: data => setToZustand(data) })\n
Run Code Online (Sandbox Code Playgroud)\n
\n

2023 年 4 月编辑:

\n

关于回调的建议onSuccess不是一个好的建议。看来我在发布这个答案时还没有完全理解后果。

\n

我们已经弃用了回调,useQuery并将在下一个主要版本(v5)中删除它们回调将不会可靠地运行,如果它们确实运行,它们将为每个实例运行,如果您想编写,这不是您想要的数据到 zustand。更好的方法是设置一个useEffect

\n
const { data } = useQuery({ queryKey, queryFn })\n\nReact.useEffect(() => {\n  if (data) {\n    setToZustand(data)\n  }\n}, [data])\n
Run Code Online (Sandbox Code Playgroud)\n

但这仍然有很多缺点,比如添加额外的渲染周期,以及在 React18 StrictMode 中运行两次(在开发环境中)。因此,最初的建议 - 您不需要在任何地方同步数据 - 仍然有效。

\n

我写了一篇关于此的详细博文

\n

  • 我认为在OP的情况下,本地/会话存储可能有用,反应查询不会在刷新时保留数据。是否有与 cookies/local/sessionStorage 交互的反应查询功能? (2认同)