我已经设置了一个Next.js应用程序,其身份验证由www.example.com处理Clerk.dev,数据存储由Supabase管理。我也在使用Zustand进行状态管理。但是,我遇到了一个错误,显示“不存在存储选项来持久化会话,这可能会导致在使用auth时出现意外行为。”
"@clerk/nextjs": "^4.16.4",
"next": "^12.0.9",
"react": "17.0.2",
"zustand": "^4.3.8"
下面是我的代码的简化版本:
文件:utils\supabase.ts
import { createClient, SupabaseClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_KEY;
export const supabase: SupabaseClient = createClient(supabaseUrl, supabaseKey);
文件:store\useUserStore.ts
import { create } from 'zustand';
import { supabase } from '../utils/supabase';
type User = {
id: string;
email: string;
custom_api: string;
bot_type: string;
discord_id: string;
};
type UserStore = {
userData: User | null;
status: 'idle' | 'loading' | 'error';
error: string | null;
fetchUser: (userId: string) => Promise<void>;
createUser: (userId: string, user: Partial<User>) => Promise<void>;
updateUser: (userId: string, updates: Partial<User>) => Promise<void>;
deleteUser: (userId: string) => Promise<void>;
};
export const useUserStore = create<UserStore>((set) => ({
userData: null,
status: 'idle',
error: null,
fetchUser: async (userId) => {
try {
set({ status: 'loading' });
const { data, error } = await supabase
.from('users')
.select()
.eq('id', userId)
if (error) {
throw new Error('Error fetching user');
}
set({ userData: data![0] ?? null, status: 'idle', error: null });
} catch (error) {
set({ status: 'error', error: error.message });
}
},
createUser: async (userId, user) => {
// code here
},
updateUser: async (userId, updates) => {
// code here
},
deleteUser: async (userId) => {
// code here
},
}));
错误消息指出不存在用于保持会话的存储选项,这可能导致在使用身份验证时出现意外行为。我想启用persistSession选项,但不确定如何继续。
对于其他上下文,我使用Clerk.dev进行身份验证,并使用JWT将其连接到Supabase。我还为SELECT操作设置了一个行级安全性(Row-LevelSecurity,RLS)策略,它针对所有(公共)角色并使用WITHCHECK表达式。
我将非常感谢有关如何解决此错误并正确配置会话存储以与www.example.com,Supabase和Zustand无缝工作的任何指导或建议Clerk.dev。谢谢你!
当时,我的代码结构如下:
import { createClient } from '@supabase/supabase-js'
import { useSession } from '@clerk/nextjs'
/// .....
const supabaseClient = async supabaseAccessToken => {
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_KEY,
{
global: { headers: { Authorization: `Bearer ${supabaseAccessToken}` } }
}
)
return supabase
}
/// .....
export default function Messages() {
//...
const { session } = useSession()
//...
const supabaseAccessToken = await session.getToken({
template: 'Supabase'
})
const supabase = await supabaseClient(supabaseAccessToken)
const { data } = await supabase
.from('user')
.insert(
{
id: session.user.id,
email: session.user?.primaryEmailAddress?.emailAddress,
}
)
.select()
setUserSettings(data[0])
//...
这段代码看起来很乱,因为我是直接在.tsx文件中执行的。我想使用状态管理(Zustand)来改进代码结构并坚持良好的实践。
1条答案
按热度按时间k7fdbhmy1#
我能够在不使用本地存储的情况下实现这一点,这是Discord社区中其他人推荐的。
起初,我不得不寻找一个替代方案。因此,我所做的是将会话管理纳入状态管理。在客户端组件中,下面是我的代码:
因此,我不再拥有
./utils/supabase.ts file
。我直接把它插入或包含在商店里。下面是我的./store/useUserStore.ts
文件:我希望这个增强的解释能够澄清我所做的更改,并提供对代码的更清晰的理解。