我正在为后端构建一个带有Next.js 13和Supabase的应用程序,我一直在寻找最佳/正确的方法来为当前登录的用户创建上下文/提供程序。
从Supabase检索用户的流程如下:
我的布局中有一个supabase侦听器,它侦听auth状态的变化,并且可以很好地设置和刷新当前会话。我最初的方法是在fetchUser变更钩子中添加onAuthState调用,但是我遇到了后期的更新水化错误。
直接从示例中获取,这是该应用程序的外观:
// layout.tsx
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const supabase = createServerComponentSupabaseClient<Database>({
headers,
cookies,
});
const {
data: { session },
} = await supabase.auth.getSession();
return (
<html>
<head />
<body>
<NavMenu session={session} />
<SupabaseListener accessToken={session?.access_token} />
{children}
</body>
</html>
);
}
// supabase-listener.tsx
// taken directly from the supabase-auth-helpers library.
"use client";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import supabase from "../lib/supabase/supabase-browser";
export default function SupabaseListener({
accessToken,
}: {
accessToken?: string;
}) {
const router = useRouter();
useEffect(() => {
supabase.auth.onAuthStateChange(async (event, session) => {
if (session?.access_token !== accessToken) {
router.refresh();
}
});
}, [accessToken, router]);
return null;
}
基本上,我只需要用一个LoggedInUserProvider包装我的根布局,在初始页面加载的某个地方进行获取用户调用,并设置当前登录的用户提供程序的状态。
我尝试过的其他方法是从根布局进行提取用户调用,并有一个LoggedInUserListener客户端组件,该组件将用户作为属性,并在配置文件存在的情况下简单地设置状态。这导致了不正确的设置状态错误。
非常感谢。
发布于 2022-12-02 23:02:54
听起来,您试图通过在初始呈现后获取用户数据来避免Next.js中的后期更新水合错误。这样做的一种方法是在布局组件中使用getInitialProps
生命周期方法。此方法允许您异步获取呈现页面所需的数据,然后将该数据作为支持传递给布局组件。
下面是一个如何实现此功能的示例:
// layout.tsx
import React, { useState } from "react";
import { useRouter } from "next/navigation";
import supabase from "../lib/supabase/supabase-browser";
function Layout({ children, user }: { children: React.ReactNode; user: User }) {
const [currentUser, setCurrentUser] = useState(user);
const router = useRouter();
useEffect(() => {
supabase.auth.onAuthStateChange(async (event, session) => {
if (session?.access_token !== accessToken) {
router.refresh();
}
});
}, [accessToken, router]);
return (
<html>
<head />
<body>
<NavMenu session={session} />
<SupabaseListener accessToken={session?.access_token} />
{children}
</body>
</html>
);
}
Layout.getInitialProps = async ({ cookies, headers }) => {
const supabase = createServerComponentSupabaseClient<Database>({
headers,
cookies,
});
const {
data: { session },
} = await supabase.auth.getSession();
// Fetch the user object here
const user = await supabase.from("users").find(session.user_id);
return { user };
};
export default Layout;
在本例中,Layout
组件获取getInitialProps
中的用户数据,并将其作为支柱传递给组件。然后,该组件使用useState
钩子将当前用户存储在本地状态,您可以使用该状态为应用程序的其余部分设置用户上下文。
您还可以使用页面中的getInitialProps
方法获取数据,并将其作为支持传递给页面组件。
我希望这能帮到你!
https://stackoverflow.com/questions/74661653
复制相似问题