首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Nexts.js 13 + Supabase >创建用户上下文的正确方法是什么

Nexts.js 13 + Supabase >创建用户上下文的正确方法是什么
EN

Stack Overflow用户
提问于 2022-12-02 21:28:11
回答 1查看 32关注 0票数 0

我正在为后端构建一个带有Next.js 13和Supabase的应用程序,我一直在寻找最佳/正确的方法来为当前登录的用户创建上下文/提供程序。

从Supabase检索用户的流程如下:

  1. 与OAuth提供程序登录。
  2. 从supabase Changed钩子获取会话中的用户ID。
  3. 使用上面提到的用户ID从supabase获取完整的用户对象。

我的布局中有一个supabase侦听器,它侦听auth状态的变化,并且可以很好地设置和刷新当前会话。我最初的方法是在fetchUser变更钩子中添加onAuthState调用,但是我遇到了后期的更新水化错误。

直接从示例中获取,这是该应用程序的外观:

代码语言:javascript
运行
复制
// 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>
  );
}
代码语言:javascript
运行
复制
// 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客户端组件,该组件将用户作为属性,并在配置文件存在的情况下简单地设置状态。这导致了不正确的设置状态错误。

非常感谢。

EN

回答 1

Stack Overflow用户

发布于 2022-12-02 23:02:54

听起来,您试图通过在初始呈现后获取用户数据来避免Next.js中的后期更新水合错误。这样做的一种方法是在布局组件中使用getInitialProps生命周期方法。此方法允许您异步获取呈现页面所需的数据,然后将该数据作为支持传递给布局组件。

下面是一个如何实现此功能的示例:

代码语言:javascript
运行
复制
// 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方法获取数据,并将其作为支持传递给页面组件。

我希望这能帮到你!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74661653

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档