Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Real-time Chat & Messaging

LinkedIn ma messaging system. Zbudujmy prosty chat!

WebSocket Connection 🔌

1import { useEffect, useState } from 'react';
2
3function useWebSocket(url: string) {
4  const [ws, setWs] = useState<WebSocket | null>(null);
5  const [messages, setMessages] = useState<any[]>([]);
6
7  useEffect(() => {
8    const socket = new WebSocket(url);
9    
10    socket.onmessage = (event) => {
11      const message = JSON.parse(event.data);
12      setMessages(prev => [...prev, message]);
13    };
14
15    setWs(socket);
16    return () => socket.close();
17  }, [url]);
18
19  const send = (message: any) => {
20    ws?.send(JSON.stringify(message));
21  };
22
23  return { messages, send };
24}
25
26function Chat({ recipientId }: { recipientId: number }) {
27  const { messages, send } = useWebSocket('ws://localhost:3001');
28  const [input, setInput] = useState("");
29
30  const handleSend = () => {
31    send({ to: recipientId, content: input });
32    setInput("");
33  };
34
35  return (
36    <div className="flex flex-col h-96">
37      <div className="flex-1 overflow-auto p-4 space-y-2">
38        {messages.map((msg, i) => (
39          <div key={i} className={msg.from === recipientId ? "text-left" : "text-right"}>
40            <span className="inline-block bg-blue-600 text-white px-4 py-2 rounded">
41              {msg.content}
42            </span>
43          </div>
44        ))}
45      </div>
46      <div className="flex gap-2 p-4 border-t">
47        <input
48          value={input}
49          onChange={(e) => setInput(e.target.value)}
50          onKeyPress={(e) => e.key === 'Enter' && handleSend()}
51          className="flex-1 border rounded px-3 py-2"
52        />
53        <button onClick={handleSend} className="bg-blue-600 text-white px-4 py-2 rounded">
54          Send
55        </button>
56      </div>
57    </div>
58  );
59}

Typing Indicators ⌨️

1function Chat() {
2  const [typing, setTyping] = useState(false);
3  const typingTimeout = useRef<NodeJS.Timeout>();
4
5  const handleTyping = () => {
6    send({ type: 'typing', userId: currentUser.id });
7    
8    if (typingTimeout.current) {
9      clearTimeout(typingTimeout.current);
10    }
11    
12    typingTimeout.current = setTimeout(() => {
13      send({ type: 'stop-typing', userId: currentUser.id });
14    }, 1000);
15  };
16
17  return (
18    <div>
19      {/* Messages */}
20      {typing && <p className="text-sm text-gray-500">User is typing...</p>}
21      <input onChange={handleTyping} />
22    </div>
23  );
24}

Do zobaczenia! 🚀

Przejdź do CodeWorlds