Supabase
Supabase 被称为 "开源的 Firebase",它基于 PostgreSQL 提供了全套的后端服务,包括数据库、身份认证、实时监控、存储以及边缘函数。
1. 核心特性
- PostgreSQL 数据库:完整的关系型数据库,具有强大的扩展性和 SQL 支持。
- 身份认证 (Auth):内置用户注册、登录(支持第三方 OAuth)以及权限管理。
- Row Level Security (RLS):基于 SQL 指令的精细权限控制,直接在数据库层保护数据。
- 实时 (Realtime):通过 Websockets 监听数据库变更。
- 存储 (Storage):用于存储和管理大型文件(图片、视频)。
2. 快速集成
安装 SDK
npm install @supabase/supabase-js
初始化客户端
建议创建一个单独的 lib/supabase.js 文件:
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
3. 基础操作事例 (CRUD)
读取数据
const { data, error } = await supabase
.from("posts")
.select("*")
.eq("status", "published");
插入数据
const { data, error } = await supabase
.from("posts")
.insert([{ title: "Hello World", user_id: "..." }]);
更新数据
const { data, error } = await supabase
.from("posts")
.update({ title: "New Title" })
.match({ id: 123 });
4. 身份认证事例
// 登录
const { user, error } = await supabase.auth.signInWithPassword({
email: "example@email.com",
password: "password123",
});
// 监听登录状态
supabase.auth.onAuthStateChange((event, session) => {
console.log(event, session);
});
5. 在 React 中的实践
身份认证 Context
为了在应用全局访问用户信息,建议创建一个 Auth Context:
import { createContext, useContext, useEffect, useState } from "react";
import { supabase } from "./supabaseClient";
const AuthContext = createContext({});
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
// 获取当前 Session
supabase.auth.getSession().then(({ data: { session } }) => {
setUser(session?.user ?? null);
});
// 监听状态变化 (登录/登出)
const {
data: { subscription },
} = supabase.auth.onAuthStateChange((_event, session) => {
setUser(session?.user ?? null);
});
return () => subscription.unsubscribe();
}, []);
return (
<AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);
数据获取与实时订阅
结合 useEffect 和 useState 实现数据的自动刷新。
import { useEffect, useState } from "react";
import { supabase } from "./supabaseClient";
function ChatRoom() {
const [messages, setMessages] = useState([]);
useEffect(() => {
// 1. 初始获取数据
fetchMessages();
// 2. 开启实时订阅
const channel = supabase
.channel("schema-db-changes")
.on(
"postgres_changes",
{ event: "INSERT", schema: "public", table: "messages" },
(payload) => {
setMessages((prev) => [...prev, payload.new]);
}
)
.subscribe();
return () => supabase.removeChannel(channel);
}, []);
const fetchMessages = async () => {
const { data } = await supabase.from("messages").select("*");
if (data) setMessages(data);
};
return (
<ul>
{messages.map((m) => (
<li key={m.id}>{m.content}</li>
))}
</ul>
);
}