英文:
How to persist and set global state for client from server in NextJS 13.4?
问题
在NextJS 13中,例如,你的导航栏位于根目录的layout.tsx文件夹中。它会检查认证,然后获取用户信息,你希望用户信息在所有页面中都可以全局使用,无论是服务器组件还是客户端组件,因为导航栏存在于每个路由中,实际上是认证会话的真实来源,如果导航栏已经完成了工作,那么在所有服务器组件上都获取用户信息是不明智的。
英文:
PROBLEM: In NextJS 13, for example, your Navbar lives in the root layout.tsx folder. It checks auth, then fetches user, you want the user to be available globally to all pages regardless of server component or client component, since the Navbar exists in every route and is essentially the source of truth for the auth session, it would be unwise to fetch users on all server components when Navbar already did the work.
答案1
得分: 2
使用https://www.youtube.com/watch?v=OpMAH2hzKi8提供的解决方案。
使用Zustand,这是一个不需要上下文包装器的全局状态管理系统:
https://www.npmjs.com/package/zustand
创建一个存储库
const useUserStore = create((set) => ({
signedIn: false,
setSignedIn: (isSignedIn) => set({ isSignedIn }),
}))
创建StoreInitializer.tsx:
"use client";
import { useRef } from "react";
import { useUserStore } from "@/store/userStore";
export function StoreInitializer({ user }: { user?: User }) {
const isInitialized = useRef(false);
if (!isInitialized.current) {
useUserStore.setState({
user,
});
isInitialized.current = true;
}
return null;
}
在根布局中
const { user } = await useServerGetAuth(); // ur own auth function
useUserStore.setState({ user: user });
return (
<html lang="en">
<body>
<NextTopLoader />
<StoreInitializer user={user} />
<Navbar />
{children}
<Footer />
</body>
</html>
);
现在只要布局在服务器端成功验证了用户,它就会设置用户。这还会防止默认值的闪烁。
英文:
Solution by https://www.youtube.com/watch?v=OpMAH2hzKi8
Using Zustand, a global state mangement system that doesn't require context wrappers:
https://www.npmjs.com/package/zustand
Create a store
const useUserStore = create((set) => ({
signedIn: false,
setSignedIn: (isSignedIn) => set({ isSignedIn }),
}))
Create StoreInitializer.tsx:
"use client";
import { useRef } from "react";
import { useUserStore } from "@/store/userStore";
export function StoreInitializer({ user }: { user?: User }) {
const isInitialized = useRef(false);
if (!isInitialized.current) {
useUserStore.setState({
user,
});
isInitialized.current = true;
}
return null;
}
In root layout
const { user } = await useServerGetAuth(); // ur own auth function
useUserStore.setState({ user: user });
return (
<html lang="en">
<body
>
<NextTopLoader />
<StoreInitializer user={user} />
<Navbar />
{children}
<Footer />
</body>
</html>
);
Now as long as the layout successfully auth'ed the user on the server side, it'll set the user. This will also prevent flash of default values.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论