creating a chat application using the MERN stack (MongoDB, Express.js, React.js, and Node.js)
Folder Structure:
- chat-app
- backend
- controllers
- models
- routes
- server.js
- frontend
- public
- src
- components
- App.js
- index.js
Backend (Node.js/Express.js):
- Create
backend/server.js
file:
const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const cors = require('cors');
// Middleware
app.use(cors());
// Socket.io
io.on('connection', (socket) => {
console.log('A user connected');
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
socket.on('disconnect', () => {
console.log('A user disconnected');
});
});
const PORT = process.env.PORT || 5000;
http.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
- Create
backend/routes/chat.js
file for handling API routes:
const express = require('express');
const router = express.Router();
// Add your chat routes here
module.exports = router;
- Create
backend/models/Message.js
file for defining the Message schema:
const mongoose = require('mongoose');
const messageSchema = new mongoose.Schema({
text: {
type: String,
required: true,
},
sender: {
type: String,
required: true,
},
timestamp: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model('Message', messageSchema);
- Create
backend/controllers/chatController.js
file for handling chat-related logic:
const Message = require('../models/Message');
// Example API endpoint
const getMessages = async (req, res) => {
try {
const messages = await Message.find().sort('-timestamp');
res.json(messages);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Server error' });
}
};
module.exports = { getMessages };
- Update
backend/server.js
to use the chat route and connect to MongoDB:
const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const cors = require('cors');
const mongoose = require('mongoose');
// Middleware
app.use(cors());
// Connect to MongoDB
mongoose.connect('mongodb://localhost/chat_app', {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
});
const connection = mongoose.connection;
connection.once('open', () => {
console.log('Connected to MongoDB');
});
// Socket.io
io.on('connection', (socket) => {
console.log('A user connected');
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
socket.on('disconnect', () => {
console.log('A user disconnected');
});
});
// Routes
const chatRouter = require('./routes/chat');
app.use('/chat', chatRouter);
const PORT = process.env.PORT || 5000;
http.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Frontend (React.js):
- Update
frontend/src/App.js
:
import React, { useEffect, useState } from 'react';
import io from 'socket.io-client';
const socket = io('http://localhost:5000');
function App() {
const [messages, setMessages] = useState([]);
const [messageInput, setMessageInput] = useState('');
useEffect(() => {
// Event listener for new messages
socket.on('chat message', (msg) => {
setMessages((prevMessages) => [...prevMessages, msg]);
});
// Clean up socket connection
return () => {
socket.disconnect();
};
}, []);
const handleSendMessage = (e) => {
e.preventDefault();
if (messageInput.trim() !== '') {
socket.emit('chat message', messageInput);
setMessageInput('');
}
};
return (
<div>
<ul>
{messages.map((msg, index) => (
<li key={index}>{msg}</li>
))}
</ul>
<form onSubmit={handleSendMessage}>
<input
type="text"
value={messageInput}
onChange={(e) => setMessageInput(e.target.value)}
/>
<button type="submit">Send</button>
</form>
</div>
);
}
export default App;
- Update
frontend/src/index.js
:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);