我想出了我的自定义React钩子来处理supabase,我不知道是否在任何地方使用这个钩子是最好的做法,因为我每次使用它都要处理isLoading
。
import { useEffect, useState } from 'react'
import { useAuth } from '@clerk/nextjs'
import { createClient } from '@supabase/supabase-js'
import { SupabaseClient } from '@supabase/supabase-js'
const createSupabaseClient = (token: string) => {
if (!process.env.NEXT_PUBLIC_SUPABASE_URL) {
throw new Error('NEXT_PUBLIC_SUPABASE_URL is not defined')
}
if (!process.env.NEXT_PUBLIC_SUPABASE_KEY) {
throw new Error('NEXT_PUBLIC_SUPABASE_KEY is not defined')
}
return createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_KEY,
{
global: {
headers: {
Authorization: `Bearer ${token}`,
},
},
},
)
}
export const useSupabase = () => {
const { getToken } = useAuth()
const [supabase, setSupabase] = useState<SupabaseClient>()
const [loading, setLoading] = useState(true)
const [error, setError] = useState()
useEffect(() => {
const fetchTokenAndInitializeClient = async () => {
try {
const token = await getToken({ template: 'supabase' })
if (!token) {
throw new Error('No token found')
}
const supabase = createSupabaseClient(token)
setSupabase(supabase)
setLoading(false)
} catch (err) {
setError(err as any)
setLoading(false)
}
}
fetchTokenAndInitializeClient()
}, [getToken])
return { supabase, loading, error }
}
1条答案
按热度按时间cnh2zyt31#
这种方法的问题是,每次调用
useSupabase
时,useEffect
都会运行,因为生命周期将从您放入的每个组件开始。你说得对,我们应该在某个地方处理这件事。
解决这个问题的一个好方法是使用
React.Context
创建一个Provider。现在,您可以将其 Package 在应用程序的顶层,如下所示:
在下面的组件中,您可以使用钩子访问
supabase
(以及它的加载和错误状态):如果不想担心所有子组件中的
loading
状态,可以在应用程序的更高位置使用guard语句,仅在loading
为false时呈现子组件。下面是一个在
SupabaseProvider
的顶层执行此操作的示例: