Cas d'utilisation
/
Développement rapide
Générez rapidement des prototypes fonctionnels
modèle
•
Claude 3.7 Sonnet
Créez un prototype d'application de chat en temps réel avec React, Node.js et Socket.io : salles de base, messagerie et présence des utilisateurs
Prototype d'application de chat en temps réel avec React, Node.js et Socket.io
Je vais vous guider dans la création d'une application de chat en temps réel de base avec assistance en salle, messagerie et indicateurs de présence des utilisateurs. Décomposons cela en composants frontend et backend.
Structure du projet
1chat-app/
2├── client/ # React frontend
3│ ├── public/
4│ └── src/
5├── server/ # Node.js backend
6└── package.jsonBackend (Node.js + Socket.IO)
1. Configuration du serveur
Tout d'abord, créez le répertoire du serveur et initialisez :
1mkdir -p chat-app/server
2cd chat-app/server
3npm init -y
4npm install express socket.io cors2. Créez server.js
1const express = require('express');
2const http = require('http');
3const socketIo = require('socket.io');
4const cors = require('cors');
5
6const app = express();
7app.use(cors());
8
9const server = http.createServer(app);
10const io = socketIo(server, {
11 cors: {
12 origin: "http://localhost:3000",
13 methods: ["GET", "POST"]
14 }
15});
16
17// Track users in each room
18const rooms = {};
19
20io.on('connection', (socket) => {
21 console.log('New client connected:', socket.id);
22
23 // User joins a room
24 socket.on('join_room', ({ username, room }) => {
25 socket.join(room);
26
27 // Initialize room if it doesn't exist
28 if (!rooms[room]) {
29 rooms[room] = [];
30 }
31
32 // Add user to room
33 rooms[room].push({ id: socket.id, username });
34
35 // Broadcast to room that user has joined
36 io.to(room).emit('user_joined', {
37 username,
38 users: rooms[room],
39 message: `${username} has joined the room.`
40 });
41
42 // Send room history to the new user
43 socket.emit('room_users', rooms[room]);
44
45 console.log(`${username} joined room: ${room}`);
46 });
47
48 // Handle messages
49 socket.on('send_message', ({ room, username, message }) => {
50 const timestamp = new Date().toISOString();
51 io.to(room).emit('receive_message', {
52 username,
53 message,
54 timestamp
55 });
56 });
57
58 // Handle user typing
59 socket.on('typing', ({ room, username }) => {
60 socket.to(room).emit('user_typing', { username });
61 });
62
63 // Handle user disconnect
64 socket.on('disconnect', () => {
65 console.log('Client disconnected:', socket.id);
66
67 // Find which room the user was in
68 for (const room in rooms) {
69 const userIndex = rooms[room].findIndex(user => user.id === socket.id);
70
71 if (userIndex !== -1) {
72 const username = rooms[room][userIndex].username;
73
74 // Remove user from room
75 rooms[room].splice(userIndex, 1);
76
77 // Notify room that user has left
78 io.to(room).emit('user_left', {
79 username,
80 users: rooms[room],
81 message: `${username} has left the room.`
82 });
83
84 break;
85 }
86 }
87 });
88});
89
90const PORT = process.env.PORT || 4000;
91server.listen(PORT, () => {
92 console.log(`Server running on port ${PORT}`);
93});Interface (React + Socket.IO-Client)
1. Configuration de l'application React
1npx create-react-app chat-app/client
2cd chat-app/client
3npm install socket.io-client2. Création de composants
src/App.js
1import React, { useState } from 'react';
2import './App.css';
3import JoinRoom from './components/JoinRoom';
4import ChatRoom from './components/ChatRoom';
5
6function App() {
7 const [joined, setJoined] = useState(false);
8 const [userData, setUserData] = useState({ username: '', room: '' });
9
10 const handleJoinRoom = (username, room) => {
11 setUserData({ username, room });
12 setJoined(true);
13 };
14
15 return (
16 <div className="App">
17 <header className="App-header">
18 <h1>Real-Time Chat App</h1>
19 </header>
20 <main>
21 {!joined ? (
22 <JoinRoom onJoin={handleJoinRoom} />
23 ) : (
24 <ChatRoom username={userData.username} room={userData.room} />
25 )}
26 </main>
27 </div>
28 );
29}
30
31export default App;src/components/JoinRoom.js
1import React, { useState } from 'react';
2
3function JoinRoom({ onJoin }) {
4 const [username, setUsername] = useState('');
5 const [room, setRoom] = useState('');
6
7 const handleSubmit = (e) => {
8 e.preventDefault();
9 if (username && room) {
10 onJoin(username, room);
11 }
12 };
13
14 return (
15 <div className="join-container">
16 <h2>Join a Chat Room</h2>
17 <form onSubmit={handleSubmit}>
18 <div className="form-group">
19 <label htmlFor="username">Username:</label>
20 <input
21 type="text"
22 id="username"
23 value={username}
24 onChange={(e) => setUsername(e.target.value)}
25 required
26 />
27 </div>
28 <div className="form-group">
29 <label htmlFor="room">Room:</label>
30 <input
31 type="text"
32 id="room"
33 value={room}
34 onChange={(e) => setRoom(e.target.value)}
35 required
36 />
37 </div>
38 <button type="submit">Join Room</button>
39 </form>
40 </div>
41 );
42}
43
44export default JoinRoom;src/components/ChatRoom.js
1import React, { useState, useEffect, useRef } from 'react';
2import io from 'socket.io-client';
3
4const ENDPOINT = 'http://localhost:4000';
5
6function ChatRoom({ username, room }) {
7 const [messages, setMessages] = useState([]);
8 const [message, setMessage] = useState('');
9 const [users, setUsers] = useState([]);
10 const [typingUsers, setTypingUsers] = useState([]);
11 const socketRef = useRef();
12 const messagesEndRef = useRef();
13
14 // Initialize socket connection
15 useEffect(() => {
16 socketRef.current = io(ENDPOINT);
17
18 // Join room
19 socketRef.current.emit('join_room', { username, room });
20
21 // Listen for messages
22 socketRef.current.on('receive_message', (data) => {
23 setMessages((prevMessages) => [...prevMessages, data]);
24 });
25
26 // Listen for user joined
27 socketRef.current.on('user_joined', (data) => {
28 setUsers(data.users);
29 setMessages((prevMessages) => [
30 ...prevMessages,
31 { system: true, message: data.message, timestamp: new Date().toISOString() }
32 ]);
33 });
34
35 // Listen for user left
36 socketRef.current.on('user_left', (data) => {
37 setUsers(data.users);
38 setMessages((prevMessages) => [
39 ...prevMessages,
40 { system: true, message: data.message, timestamp: new Date().toISOString() }
41 ]);
42 });
43
44 // Get current users in room
45 socketRef.current.on('room_users', (data) => {
46 setUsers(data);
47 });
48
49 // Listen for typing events
50 socketRef.current.on('user_typing', (data) => {
51 setTypingUsers((prevTypers) => {
52 if (!prevTypers.includes(data.username)) {
53 return [...prevTypers, data.username];
54 }
55 return prevTypers;
56 });
57
58 // Remove typing indicator after 2 seconds
59 setTimeout(() => {
60 setTypingUsers((prevTypers) =>
61 prevTypers.filter(user => user !== data.username)
62 );
63 }, 2000);
64 });
65
66 // Cleanup on unmount
67 return () => {
68 socketRef.current.disconnect();
69 };
70 }, [username, room]);
71
72 // Auto-scroll to bottom when new messages arrive
73 useEffect(() => {
74 messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
75 }, [messages]);
76
77 // Handle sending messages
78 const handleSendMessage = (e) => {
79 e.preventDefault();
80 if (message.trim()) {
81 socketRef.current.emit('send_message', {
82 room,
83 username,
84 message
85 });
86 setMessage('');
87 }
88 };
89
90 // Handle typing indicator
91 const handleTyping = () => {
92 socketRef.current.emit('typing', { room, username });
93 };
94
95 // Format timestamp
96 const formatTime = (timestamp) => {
97 return new Date(timestamp).toLocaleTimeString([], {
98 hour: '2-digit',
99 minute: '2-digit'
100 });
101 };
102
103 return (
104 <div className="chat-container">
105 <div className="chat-header">
106 <h2>Room: {room}</h2>
107 </div>
108
109 <div className="chat-main">
110 <div className="chat-sidebar">
111 <h3>Users in Room</h3>
112 <ul className="users-list">
113 {users.map((user, index) => (
114 <li key={index} className={user.username === username ? 'current-user' : ''}>
115 {user.username} {user.username === username ? '(You)' : ''}
116 </li>
117 ))}
118 </ul>
119 </div>
120
121 <div className="chat-messages">
122 {messages.map((msg, index) => (
123 <div
124 key={index}
125 className={`message ${msg.system ? 'system-message' :
126 (msg.username === username ? 'my-message' : 'other-message')}`}
127 >
128 {!msg.system && (
129 <div className="message-header">
130 <span className="username">{msg.username}</span>
131 <span className="timestamp">{formatTime(msg.timestamp)}</span>
132 </div>
133 )}
134 <p className="message-text">{msg.message}</p>
135 </div>
136 ))}
137
138 {typingUsers.length > 0 && (
139 <div className="typing-indicator">
140 {typingUsers.join(', ')} {typingUsers.length === 1 ? 'is' : 'are'} typing...
141 </div>
142 )}
143
144 <div ref={messagesEndRef} />
145 </div>
146 </div>
147
148 <form className="message-form" onSubmit={handleSendMessage}>
149 <input
150 type="text"
151 value={message}
152 onChange={(e) => setMessage(e.target.value)}
153 onKeyPress={handleTyping}
154 placeholder="Type a message..."
155 />
156 <button type="submit">Send</button>
157 </form>
158 </div>
159 );
160}
161
162export default ChatRoom;3. Ajoutez un peu de CSS de base
src/App.css
1* {
2 box-sizing: border-box;
3 margin: 0;
4 padding: 0;
5}
6
7body {
8 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
9 line-height: 1.6;
10 background-color: #f5f5f5;
11}
12
13.App {
14 max-width: 1200px;
15 margin: 0 auto;
16 padding: 1rem;
17}
18
19.App-header {
20 text-align: center;
21 margin-bottom: 2rem;
22 color: #333;
23}
24
25/* Join Room Styles */
26.join-container {
27 max-width: 500px;
28 margin: 0 auto;
29 background: white;
30 border-radius: 8px;
31 padding: 2rem;
32 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
33}
34
35.join-container h2 {
36 margin-bottom: 1.5rem;
37 text-align: center;
38}
39
40.form-group {
41 margin-bottom: 1rem;
42}
43
44.form-group label {
45 display: block;
46 margin-bottom: 0.5rem;
47 font-weight: 500;
48}
49
50.form-group input {
51 width: 100%;
52 padding: 0.75rem;
53 border: 1px solid #ddd;
54 border-radius: 4px;
55 font-size: 1rem;
56}
57
58button {
59 background-color: #4caf50;
60 color: white;
61 border: none;
62 padding: 0.75rem 1.5rem;
63 font-size: 1rem;
64 border-radius: 4px;
65 cursor: pointer;
66 transition: background-color 0.2s;
67}
68
69button:hover {
70 background-color: #45a049;
71}
72
73/* Chat Room Styles */
74.chat-container {
75 display: flex;
76 flex-direction: column;
77 height: 80vh;
78 background: white;
79 border-radius: 8px;
80 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
81}
82
83.chat-header {
84 padding: 1rem;
85 background: #4caf50;
86 color: white;
87 border-top-left-radius: 8px;
88 border-top-right-radius: 8px;
89}
90
91.chat-main {
92 display: flex;
93 flex: 1;
94 overflow: hidden;
95}
96
97.chat-sidebar {
98 width: 200px;
99 background: #f8f8f8;
100 padding: 1rem;
101 border-right: 1px solid #ddd;
102 overflow-y: auto;
103}
104
105.chat-sidebar h3 {
106 margin-bottom: 1rem;
107 font-size: 1.1rem;
108}
109
110.users-list {
111 list-style: none;
112}
113
114.users-list li {
115 padding: 0.5rem 0;
116 border-bottom: 1px solid #eee;
117}
118
119.current-user {
120 font-weight: bold;
121 color: #4caf50;
122}
123
124.chat-messages {
125 flex: 1;
126 padding: 1rem;
127 overflow-y: auto;
128}
129
130.message {
131 margin-bottom: 1rem;
132 padding: 0.75rem;
133 border-radius: 8px;
134 max-width: 80%;
135}
136
137.my-message {
138 background-color: #e3f2fd;
139 margin-left: auto;
140}
141
142.other-message {
143 background-color: #f1f1f1;
144}
145
146.system-message {
147 background-color: #fffde7;
148 text-align: center;
149 font-style: italic;
150 padding: 0.5rem;
151 margin: 0.5rem auto;
152 max-width: 90%;
153 color: #666;
154}
155
156.message-header {
157 display: flex;
158 justify-content: space-between;
159 margin-bottom: 0.5rem;
160 font-size: 0.85rem;
161}
162
163.username {
164 font-weight: bold;
165}
166
167.timestamp {
168 color: #777;
169}
170
171.typing-indicator {
172 font-style: italic;
173 color: #777;
174 padding: 0.5rem;
175}
176
177.message-form {
178 display: flex;
179 padding: 1rem;
180 border-top: 1px solid #ddd;
181}
182
183.message-form input {
184 flex: 1;
185 padding: 0.75rem;
186 border: 1px solid #ddd;
187 border-radius: 4px;
188 margin-right: 0.5rem;
189 font-size: 1rem;
190}Exécution de l'application
1. Démarrez le serveur :
1cd chat-app/server
2node server.js2. Démarrez le client React :
1cd chat-app/client
2npm start3. Ouvrez votre navigateur pour http://localhost:3000
Fonctionnalités mises en œuvre
- Chat basé sur la salle:
- Les utilisateurs peuvent rejoindre des salons de discussion spécifiques
- Plusieurs pièces peuvent exister simultanément
- Messagerie en temps réel:
- Les messages sont transmis instantanément à tous les utilisateurs de la salle
- Présence des utilisateurs:
- Montre qui se trouve actuellement dans la pièce
- Notifications lorsque les utilisateurs rejoignent ou quittent
- Indicateurs de saisie:
- Indique quand quelqu'un est en train de taper un message
- Formatage des messages:
- Différents styles pour vos messages par rapport aux autres
- Messages système pour les événements d'adhésion/de départ
- Horodatage des messages
Ce prototype fournit une base solide pour une application de chat en temps réel. Vous pouvez l'étendre avec des fonctionnalités telles que :
- Authentification des utilisateurs
- Historique des messages persistants
- Messagerie privée
- Partage de fichiers
- Lire les reçus
- Emojis/réactions personnalisés
Explorez les cas d'utilisation associés
Découvrez l'assistant IA de Ninja
Essayez gratuitement dès aujourd'hui. Forfaits à partir de 19$ par mois.


