Xây dựng Chat Real-Time với Supabase và React – Hướng Dẫn Chi Tiết

06/03/2026 P T P Chung 11 phút đọc 0 bình luận

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@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-idyour-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!

Quảng cáo

728x90 Bottom Advertisement

Thay thế bằng mã Google AdSense

Chia sẻ bài viết

Facebook Twitter

Bình luận

Chia sẻ ý kiến của bạn về bài viết này

Viết bình luận

Bình luận của bạn sẽ được kiểm duyệt trước khi hiển thị

Chưa có bình luận nào

Hãy là người đầu tiên bình luận về bài viết này!