使用NextJS+SWR+Supabase无法获取数据,出现404及无限加载
问题:使用SWR + Supabase 获取数据时出现404错误及无限加载
核心错误:你将Supabase的QueryBuilder对象直接传给了SWR的第一个参数,而SWR期望该参数是可用于fetch的URL字符串(或可序列化的缓存键)。fetcher收到QueryBuilder对象后会尝试将其转为无效URL,触发404错误,进而导致SWR不断重试,出现无限加载。
修正方案一:使用Supabase原生查询作为SWR fetcher(推荐)
直接在fetcher中执行Supabase查询逻辑,用字符串作为SWR的缓存标识:
import { supabase } from "@/lib/supabaseClient"; import useSWR from "swr"; type Product = { id: number; name: string; price: number; description: string; wallet: string; created_at: string | null; updated_at: string | null; }; // 自定义fetcher,执行Supabase查询并处理错误 const supabaseFetcher = async () => { const { data, error } = await supabase.from("products").select("*"); if (error) throw error; return data; }; function Products() { const { data, error, isLoading } = useSWR("products", supabaseFetcher); // 处理加载状态和错误 if (error) return <div>加载失败:{error.message}</div>; if (isLoading) return <div>加载中...</div>; return ( <div className="mx-[12px] mb-[12px] flex flex-col items-center justify-center gap-[12px] gap-[24px] rounded-large border border-dashed border-zinc-700 bg-[#161618]/50 p-[36px] text-white hover:bg-gray-500/20 lg:flex-row"> {data?.map((product: Product) => ( <div key={product.id}>{product.name}</div> ))} </div> ); } export { Products };
修正方案二:手动构造Supabase REST API请求URL
若需保留自定义fetch逻辑,需手动拼接Supabase REST API的URL并添加认证头:
import { supabase } from "@/lib/supabaseClient"; import useSWR from "swr"; type Product = { id: number; name: string; price: number; description: string; wallet: string; created_at: string | null; updated_at: string | null; }; // 带认证头的fetcher const fetcher = (url: RequestInfo | URL) => fetch(url, { headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "", Authorization: `Bearer ${process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || ""}`, }, }).then((res) => { if (!res.ok) throw new Error(`请求失败:${res.status}`); return res.json(); }); function Products() { // 构造Supabase REST API的查询URL const productUrl = `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/products?select=*`; const { data, error, isLoading } = useSWR(productUrl, fetcher); if (error) return <div>加载失败:{error.message}</div>; if (isLoading) return <div>加载中...</div>; return ( <div className="mx-[12px] mb-[12px] flex flex-col items-center justify-center gap-[12px] gap-[24px] rounded-large border border-dashed border-zinc-700 bg-[#161618]/50 p-[36px] text-white hover:bg-gray-500/20 lg:flex-row"> {data?.map((product: Product) => ( <div key={product.id}>{product.name}</div> ))} </div> ); } export { Products };
额外检查项
- 确认Supabase控制台中
products表已创建,且在「Authentication → Policies」中开启了匿名用户的读取权限(否则会返回403错误) - 验证
.env.local文件中的NEXT_PUBLIC_SUPABASE_URL和NEXT_PUBLIC_SUPABASE_ANON_KEY配置正确,无拼写错误
内容的提问来源于stack exchange,提问作者sllmn
相关产品推荐
相关产品推荐

