0Pricing
React Academy · บทเรียน

การสร้างคอมโพเนนต์แชตแบบเรียลไทม์

แสดงข้อความสดในรายการแชตที่เลื่อนได้ โดยใช้อีเวนต์ WebSocket และสถานะ React

การสร้างคอมโพเนนต์แชตแบบเรียลไทม์ เป็นบทเรียน React Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน

สถาปัตยกรรมคอมโพเนนต์แชต

แชตแบบเรียลไทม์มีสามส่วน ได้แก่ รายการข้อความ (แสดงผล) ช่องป้อนข้อความ (ส่ง) และชั้นการเชื่อมต่อ WebSocket/Socket.IO ควรเก็บตรรกะซ็อกเก็ตไว้ในฮุกกำหนดเอง

โครงสร้างข้อมูลข้อความ

กำหนดอินเทอร์เฟซ TypeScript สำหรับข้อความแชต เพื่อให้ชนิดข้อมูลของคอมโพเนนต์ปลอดภัยตลอดการทำงาน

interface Message {
  id: string;
  text: string;
  sender: string;
  timestamp: number;
}

const [messages, setMessages] = useState<Message[]>([]);

ฮุก useChat

ห่อหุ้มการเชื่อมต่อ สถานะข้อความ และฟังก์ชันส่งไว้ในฮุกเดียว

function useChat(roomId: string) {
  const [messages, setMessages] = useState<Message[]>([]);

  useEffect(() => {
    socket.connect();
    socket.emit('join-room', roomId);
    socket.on('message', (msg: Message) => setMessages(m => [...m, msg]));
    return () => {
      socket.off('message');
      socket.emit('leave-room', roomId);
      socket.disconnect();
    };
  }, [roomId]);

  const sendMessage = useCallback((text: string) => {
    const msg: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
    socket.emit('message', msg);
  }, []);

  return { messages, sendMessage };
}

คอมโพเนนต์รายการข้อความ

แสดงข้อความในรายการที่เลื่อนได้ ใช้ useRef กับจุดสัญญาณด้านล่าง แล้วเลื่อนไปยังจุดนั้นเมื่อมีข้อความใหม่เข้ามา

function MessageList({ messages }: { messages: Message[] }) {
  const bottomRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  return (
    <div className="message-list">
      {messages.map(msg => (
        <div key={msg.id} className={`msg ${msg.sender === 'me' ? 'mine' : 'theirs'}`}>
          <span>{msg.sender}</span>
          <p>{msg.text}</p>
        </div>
      ))}
      <div ref={bottomRef} />
    </div>
  );
}

คอมโพเนนต์ช่องป้อนข้อความ

ช่องป้อนข้อมูลแบบควบคุมที่ส่งข้อมูลเมื่อกด Enter หรือคลิกปุ่ม ล้างช่องป้อนข้อมูลหลังจากส่ง

function MessageInput({ onSend }: { onSend: (text: string) => void }) {
  const [text, setText] = useState('');

  const handleSend = () => {
    if (!text.trim()) return;
    onSend(text.trim());
    setText('');
  };

  return (
    <div className="input-row">
      <input
        value={text}
        onChange={e => setText(e.target.value)}
        onKeyDown={e => e.key === 'Enter' && handleSend()}
        placeholder="Type a message..."
      />
      <button onClick={handleSend}>Send</button>
    </div>
  );
}

การประกอบส่วนติดต่อผู้ใช้แชต

ประกอบฮุกและคอมโพเนนต์ย่อยให้เป็นคอมโพเนนต์ ChatRoom

function ChatRoom({ roomId }: { roomId: string }) {
  const { messages, sendMessage } = useChat(roomId);

  return (
    <div className="chat-room">
      <h2>Room: {roomId}</h2>
      <MessageList messages={messages} />
      <MessageInput onSend={sendMessage} />
    </div>
  );
}

การอัปเดตแบบมองโลกในแง่ดี

เพิ่มข้อความลงในสถานะภายในเครื่องทันที ก่อนที่เซิร์ฟเวอร์จะยืนยัน เพื่อให้ผู้ใช้ได้รับการตอบสนองทันที หากเซิร์ฟเวอร์ส่งข้อผิดพลาดกลับมา ให้ปรับข้อมูลให้ตรงกันหรือลบข้อความนั้นออก

const sendMessage = useCallback((text: string) => {
  const optimistic: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
  setMessages(m => [...m, optimistic]); // instant feedback
  socket.emit('message', optimistic, (err) => {
    if (err) setMessages(m => m.filter(msg => msg.id !== optimistic.id));
  });
}, []);

ตัวบ่งชี้การพิมพ์

ส่งเหตุการณ์ typing เมื่ออินพุตเปลี่ยนแปลง (โดยหน่วงเวลา) และรับฟังเหตุการณ์การพิมพ์ของผู้อื่นเพื่อแสดงตัวบ่งชี้

const emitTyping = useMemo(() => debounce(() => socket.emit('typing'), 300), []);

useEffect(() => {
  socket.on('user-typing', (user) => setTypingUser(user));
  return () => socket.off('user-typing');
}, []);

การประทับเวลาข้อความ

จัดรูปแบบการประทับเวลาด้วย Intl.DateTimeFormat เพื่อให้แสดงผลตามท้องถิ่น

function formatTime(ts: number) {
  return new Intl.DateTimeFormat('en', { hour: '2-digit', minute: '2-digit' }).format(ts);
}

<span className="timestamp">{formatTime(msg.timestamp)}</span>

การยืนยันการอ่าน

ส่งเหตุการณ์ read เมื่อผู้ใช้ดูข้อความ และรับฟังการยืนยันการอ่านจากเซิร์ฟเวอร์เพื่อแสดงเครื่องหมายถูก

รายการข้อความแบบเสมือน

สำหรับประวัติแชตที่ยาว ให้ใช้ react-window หรือ react-virtual เพื่อทำให้รายการข้อความเป็นเสมือนและแสดงผลเฉพาะแถวที่มองเห็น

การจำกัดประวัติข้อความ

จำกัดจำนวนสมาชิกในอาร์เรย์ข้อความของสถานะ เพื่อป้องกันการใช้หน่วยความจำเพิ่มขึ้นอย่างไม่มีขอบเขตในเซสชันที่ยาวนาน

socket.on('message', (msg: Message) => {
  setMessages(prev => [...prev.slice(-499), msg]); // keep last 500
});

ตรวจสอบอย่างรวดเร็ว

จุดประสงค์ของการเลื่อนไปยังองค์ประกอบจุดสัญญาณด้านล่างเมื่อมีข้อความใหม่เข้ามาในรายการแชตคืออะไร

สรุปทบทวน

สร้างแชตแบบเรียลไทม์ด้วยฮุก useChat ที่ห่อหุ้มตรรกะซ็อกเก็ต รายการ MessageList ที่เลื่อนลงอัตโนมัติ และ MessageInput ที่ล้างช่องป้อนข้อมูลเมื่อส่ง ใช้การอัปเดตแบบมองโลกในแง่ดีเพื่อให้ตอบสนองทันที และจำกัดประวัติข้อความเพื่อหลีกเลี่ยงหน่วยความจำรั่ว

คำถามที่พบบ่อย

บทเรียน “การสร้างคอมโพเนนต์แชตแบบเรียลไทม์” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การสร้างคอมโพเนนต์แชตแบบเรียลไทม์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การสร้างคอมโพเนนต์แชตแบบเรียลไทม์”

แสดงข้อความสดในรายการแชตที่เลื่อนได้ โดยใช้อีเวนต์ WebSocket และสถานะ React คุณปฏิบัติ React Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การสร้างคอมโพเนนต์แชตแบบเรียลไทม์” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน React Academy นี้ได้ไหม

ได้ บทเรียน React Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน WebSocket ในเบราว์เซอร์
  2. การใช้ Socket.IO กับ React
  3. การสร้างคอมโพเนนต์แชตแบบเรียลไทม์
  4. การเชื่อมต่อใหม่ การจัดการข้อผิดพลาด และการล้างข้อมูล
← กลับไปที่ React Academy