LinkedIn ma messaging system. Zbudujmy prosty chat!
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}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! 🚀