【问题标题】:Nexts.js 13 + Supabase > What's the proper way to create a user contextNext.js 13 + Supabase > 创建用户上下文的正确方法是什么
【发布时间】:2022-12-03 07:35:28
【问题描述】:

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

从 Supabase 检索用户的流程是这样的:

  1. 使用 OAuth 提供商登录。
  2. 从 supabase onAuthState Changed 挂钩的会话中获取用户 ID。
  3. 使用上述用户 ID 从 supabase 数据库中获取完整的用户对象。

    我的布局中有一个 supabase 侦听器,用于侦听身份验证状态更改,并且可以很好地设置和刷新当前会话。 我最初的方法是从 onAuthState changed 挂钩中添加 fetchUser 调用,但是我遇到了延迟更新水合作用错误。

    直接取自示例,这是应用程序的外观:

    // 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 客户端组件,如果配置文件存在则简单地设置状态。这导致了不正确的设置状态错误。

    太感谢了。

【问题讨论】:

    标签: reactjs next.js react-context supabase next.js13


    【解决方案1】:

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

    以下是您如何实现此功能的示例:

    // 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 中的用户数据并将其作为 prop 传递给组件。该组件然后使用 useState 挂钩将当前用户存储在本地状态,您可以使用它来为您的应用程序的其余部分设置用户上下文。

    您还可以在页面中使用 getInitialProps 方法来获取数据并将其作为 props 传递给页面组件。

    我希望这有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      • 1970-01-01
      • 2021-01-27
      • 1970-01-01
      相关资源
      最近更新 更多