Mở đầu
Trong thời đại số, chat real-time đã trở thành một phần không thể thiếu của nhiều ứng dụng web và di động. Từ tin nhắn trực tiếp trong mạng xã hội, hệ thống hỗ trợ khách hàng, đến các ứng dụng làm việc nhóm, khả năng gửi và nhận tin nhắn tức thì mang lại trải nghiệm liền mạch và tương tác cao. Việc xây dựng một hệ thống chat real-time từ đầu có thể phức tạp, đòi hỏi kiến thức về WebSocket, server-side events, và cơ sở dữ liệu thời gian thực.
Tuy nhiên, với sự phát triển của các nền tảng Backend-as-a-Service (BaaS) như Supabase, quá trình này đã trở nên đơn giản hơn rất nhiều. Supabase cung cấp cơ sở dữ liệu PostgreSQL với khả năng lắng nghe thay đổi dữ liệu theo thời gian thực, kết hợp với các hàm bảo mật và xác thực tích hợp sẵn. Khi kết hợp với React - một trong những thư viện frontend phổ biến nhất hiện nay, chúng ta có thể xây dựng một hệ thống chat real-time mạnh mẽ một cách nhanh chóng và hiệu quả.
Trong bài viết này, chúng ta sẽ cùng nhau khám phá cách xây dựng một hệ thống chat real-time đơn giản nhưng đầy đủ chức năng, sử dụng Supabase làm backend và React làm frontend. Bài viết sẽ hướng dẫn chi tiết từng bước, từ việc thiết lập dự án, tạo database, đến việc viết code frontend và kết nối real-time.
Chuẩn bị dự án
Tạo dự án Supabase
Để bắt đầu, bạn cần có một tài khoản Supabase. Truy cập vào app.supabase.com, đăng nhập hoặc đăng ký một tài khoản mới, sau đó tạo một dự án mới. Đặt tên cho dự án (ví dụ: "realtime-chat") và chọn khu vực server phù hợp.
Sau khi dự án được tạo, bạn sẽ được cung cấp một Project URL và một anon public key. Hai thông tin này sẽ được sử dụng để kết nối ứng dụng React với Supabase.
Thiết lập database
Trong Supabase, chúng ta cần tạo một bảng để lưu trữ tin nhắn. Truy cập vào tab SQL Editor và chạy câu lệnh SQL sau:
CREATE TABLE public.messages (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
ALTER TABLE public.messages ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can insert own messages." ON public.messages
FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can view own messages." ON public.messages
FOR SELECT USING (auth.uid() = user_id);
Đoạn SQL trên tạo bảng messages với các cột: id (khóa chính), user_id (liên kết với bảng auth), message (nội dung tin nhắn), và created_at (thời gian tạo). Row Level Security (RLS) được bật để đảm bảo chỉ người dùng được ủy quyền mới có thể truy cập dữ liệu của mình.
Khởi tạo dự án React
Mở terminal và chạy lệnh sau để tạo một dự án React mới:
npx create-react-app realtime-chat
cd realtime-chat
Tiếp theo, cài đặt các thư viện cần thiết:
npm install @supabase/supabase-js
npm install @supabase/auth-ui-react @supabase/auth-ui-shared
npm install framer-motion
- @supabase/supabase-js: Thư viện chính thức của Supabase để tương tác với backend.
- @supabase/auth-ui-react và @supabase/auth-ui-shared: Components UI cho authentication.
- framer-motion: Thư viện animation cho React (tùy chọn, để tăng trải nghiệm người dùng).
Xây dựng frontend với React
Thiết lập kết nối Supabase
Tạo một file supabaseClient.js trong thư mục src:
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'https://your-project-id.supabase.co'
const supabaseAnonKey = 'your-anon-public-key'
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
Thay thế your-project-id và your-anon-public-key bằng thông tin từ dự án Supabase của bạn.
Tạo components
Component ChatContainer
Tạo file ChatContainer.js:
import { useEffect, useState } from 'react'
import { supabase } from './supabaseClient'
function ChatContainer() {
const [messages, setMessages] = useState([])
const [newMessage, setNewMessage] = useState('')
useEffect(() => {
fetchMessages()
const subscription = supabase
.from('messages')
.on('INSERT', payload => {
setMessages(prev => [...prev, payload.new])
})
.subscribe()
return () => supabase.removeSubscription(subscription)
}, [])
Quảng cáo
300x250 In-Content Advertisement
const fetchMessages = async () => {
const { data, error } = await supabase
.from('messages')
.select('*')
.order('created_at', { ascending: false })
.limit(50)
if (error) console.error(error)
else setMessages(data.reverse())
}
const sendMessage = async () => {
if (!newMessage.trim()) return
const { user } = supabase.auth.getSession()
const { error } = await supabase
.from('messages')
.insert([{ user_id: user.id, message: newMessage }])
if (error) console.error(error)
else setNewMessage('')
}
return (
<div className="chat-container">
<div className="messages">
{messages.map(msg => (
<div key={msg.id} className="message">
<strong>{msg.user_id}:</strong> {msg.message}
</div>
))}
</div>
<div className="input-container">
<input
value={newMessage}
onChange={e => setNewMessage(e.target.value)}
onKeyPress={e => e.key === 'Enter' && sendMessage()}
placeholder="Nhập tin nhắn..."
/>
<button onClick={sendMessage}>Gửi</button>
</div>
</div>
)
}
export default ChatContainer
Component Auth
Tạo file Auth.js:
import { useEffect } from 'react'
import { SessionContext, SupabaseAuthClient, useAuth } from '@supabase/auth-ui-react'
import { ThemeProvider } from '@supabase/auth-ui-shared'
import { supabase } from './supabaseClient'
function Auth() {
const { user, signInWithOAuth } = useAuth()
useEffect(() => {
supabase.auth.getSession()
}, [])
return (
<div className="auth-container">
{!user ? (
<button onClick={() => signInWithOAuth('google')}>Đăng nhập với Google</button>
) : (
<div>Xin chào, {user.user_metadata?.full_name || user.email}</div>
)}
</div>
)
}
export default Auth
Tích hợp vào App.js
Cập nhật file App.js:
import { useEffect } from 'react'
import { SessionContext, SupabaseAuthClient, ThemeProvider } from '@supabase/auth-ui-react'
import { supabase } from './supabaseClient'
import Auth from './Auth'
import ChatContainer from './ChatContainer'
function App() {
return (
<ThemeProvider>
<SessionContext client={supabase.auth}>
<div className="app">
<Auth />
<ChatContainer />
</div>
</SessionContext>
</ThemeProvider>
)
}
export default App
Kết luận
Trong bài viết này, chúng ta đã cùng nhau xây dựng một hệ thống chat real-time đơn giản nhưng đầy đủ chức năng, sử dụng Supabase làm backend và React làm frontend. Nhờ vào khả năng lắng nghe thay đổi dữ liệu theo thời gian thực của Supabase, chúng ta có thể dễ dàng cập nhật giao diện người dùng mỗi khi có tin nhắn mới được gửi đi.
Hệ thống này có thể được mở rộng thêm nhiều tính năng khác như: - Phân biệt người gửi và người nhận bằng màu sắc hoặc style khác nhau. - Thêm thời gian gửi tin nhắn. - Hỗ trợ upload file hoặc hình ảnh. - Tạo phòng chat hoặc nhóm chat. - Thông báo real-time khi có tin nhắn mới.
Supabase cung cấp một giải pháp toàn diện, từ database, authentication, đến real-time subscriptions, giúp giảm đáng kể thời gian và công sức phát triển. Kết hợp với React, chúng ta có thể tạo ra những ứng dụng web hiện đại, tương tác cao và dễ bảo trì.
Hy vọng bài viết này đã cung cấp cho bạn cái nhìn tổng quan và hướng dẫn chi tiết để bắt đầu xây dựng hệ thống chat real-time của riêng mình. Chúc bạn thành công và có những trải nghiệm thú vị với Supabase và React!