import React, { useState, useContext, useEffect } from 'react';
import axios from 'axios';
import AuthContext from "../context/AuthContext";
const MessagingComponent = () => {
const [messages, setMessages] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [newMessage, setNewMessage] = useState(''); // State to handle new message input
const { user, isLoading: isUserLoading } = useContext(AuthContext);
const [currentChatId, setCurrentChatId] = useState(null);
const fetchMessages = async () => {
try {
if (!user) {
console.error('User not found in AuthContext');
setIsLoading(false); // Set isLoading to false to handle the case where user is not found
return;
}
// Fetch messages associated with the user from MongoDB
const response = await axios.get(`http://localhost:5000/api/messages/${user._id}`, {
headers: {
Authorization: `Bearer ${user.token}`, // Use token from AuthContext
},
});
// Set messages state with fetched messages
setMessages(response.data.messages);
setIsLoading(false);
} catch (error) {
console.error('Error fetching messages:', error);
setIsLoading(false); // Set isLoading to false in case of error
}
};
useEffect(() => {
if (!isUserLoading) {
fetchMessages();
}
}, [user, fetchMessages, isUserLoading]); // Fetch messages whenever user changes or isUserLoading changes
const sendMessage = async (event) => {
event.preventDefault();
try {
if (!user) {
console.error('User not found in AuthContext');
return;
}
await axios.post(`http://localhost:5000/send-message`, {
userId: user._id,
content: newMessage,
chatId: currentChatId, // Add the chatId to the message
}, {
headers: {
Authorization: `Bearer ${user.token}`, // Use token from AuthContext
},
});
setNewMessage(''); // Clear the input field
fetchMessages(); // Fetch messages again to update the list
} catch (error) {
console.error('Error sending message:', error);
}
};
return (
<div>
<h2>Previous Messages</h2>
{isLoading ? (
<p>Loading messages...</p>
) : messages.length === 0 ? (
<p>No previous messages.</p>
) : (
<ul>
{messages.map((message, index) => (
<li key={index}>
<p>From: {message.sender}</p>
<p>To: {message.recipient}</p>
<p>Message: {message.content}</p>
</li>
))}
</ul>
)}
<form onSubmit={sendMessage}>
<input
type="text"
value={newMessage}
onChange={(e) => setNewMessage(e.target.value)}
placeholder="Type your message here..."
/>
<button type="submit">Send</button>
</form>
</div>
);
};
export default MessagingComponent;
//authcontext.js
import { createContext, useContext, useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
// import { toast, ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import ToastContext from "./ToastContext";
const AuthContext = createContext();
export const AuthContextProvider = ({ children }) => {
const { toast } = useContext(ToastContext);
const navigate = useNavigate();
const location = useLocation();
const [user, setUser] = useState(null);
// const [error, setError] = useState(null);
// check if the user is logged in.
// const checkUserLoggedIn = async () => {
// try {
// const res = await fetch(`http://localhost:8000/api/me`, {
// method: "GET",
// headers: {
// Authorization: `Bearer ${localStorage.getItem("token")}`,
// },
// });
// const result = await res.json();
// if (!result.error) {
// if (
// location.pathname === "/login" ||
// location.pathname === "/register"
// ) {
// setTimeout(() => {
// navigate("/", { replace: true });
// }, 500);
// } else {
// navigate(location.pathname ? location.pathname : "/");
// }
// setUser(result);
// } else {
// navigate("/login", { replace: true });
// }
// } catch (err) {
// console.log(err);
// }
// };
// useEffect(() => {
// checkUserLoggedIn();
// }, [checkUserLoggedIn]);
useEffect(() => {
// check if the user is logged in.
const checkUserLoggedIn = async () => {
try {
const res = await fetch(`http://localhost:8000/api/me`, {
method: "GET",
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
const result = await res.json();
if (!result.error) {
if (
location.pathname === "/login" ||
location.pathname === "/register"
) {
setTimeout(() => {
navigate("/", { replace: true });
}, 500);
} else {
navigate(location.pathname ? location.pathname : "/");
}
setUser(result);
} else {
navigate("/login", { replace: true });
}
} catch (err) {
console.log(err);
}
};
checkUserLoggedIn();
}, [navigate, setUser, location.pathname]);
// login request.
const loginUser = async (userData) => {
try {
const res = await fetch(`http://localhost:8000/api/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ ...userData }),
});
const result = await res.json();
if (!result.error) {
localStorage.setItem("token", result.token);
setUser(result.user);
toast.success(`Logged in ${result.user.name}`);
navigate("/", { replace: true });
} else {
toast.error(result.error);
}
} catch (err) {
console.log(err);
}
};
// register request.
const registerUser = async (userData) => {
try {
const res = await fetch(`http://localhost:8000/api/register`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ ...userData }),
});
const result = await res.json();
if (!result.error) {
toast.success("user registered successfully! login into your account!");
navigate("/login", { replace: true });
} else {
toast.error(result.error);
}
} catch (err) {
console.log(err);
}
};
return (
<AuthContext.Provider value={{ loginUser, registerUser, user, setUser }}>
{children}
</AuthContext.Provider>
);
};
export default AuthContext;
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const mongoose = require('mongoose');
const { isValidObjectId } = mongoose.Types.ObjectId;
require("dotenv").config();
const app = express();
// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('MongoDB connected'))
.catch(err => console.error('MongoDB connection error:', err));
// Load models
const Message = require('./models/messages');
const User = require('./models/user');
const Contact = require('./models/contact');
app.use(bodyParser.json());
// Route to handle fetching messages for a specific user
app.get('/api/messages/:chatId', async (req, res) => {
try {
const { chatId } = req.params;
const messages = await Message.find({ chatId: chatId });
return res.status(200).json({ messages });
} catch (error) {
console.error('Error fetching messages:', error);
return res.status(500).json({ error: 'Internal server error' });
}
});
// Route to handle sending messages and returning sent messages
app.post('/send-message', async (req, res) => {
try {
const { userId, message } = req.body;
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
const contacts = await Contact.find({ postedBy: userId });
if (!contacts.length) {
return res.status(400).json({ error: 'No contacts found for the user' });
}
const sentMessages = await sendMessagesToContacts(user, contacts, message);
await Message.insertMany(sentMessages);
return res.status(200).json({ message: 'Messages sent successfully', sentMessages });
} catch (error) {
console.error('Error sending messages:', error);
return res.status(500).json({ error: 'Internal server error' });
}
});
async function sendMessagesToContacts(user, contacts, message) {
const sentMessages = [];
for (const contact of contacts) {
const options = {
method: 'POST',
url: 'https://send.api.mailtrap.io/api/send',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'Api-Token': process.env.MAILTRAP_API_TOKEN
},
body: {
to: [{ email: contact.email, name: contact.name }],
from: { email: '[email protected]', name: 'Example Sales Team' },
subject: 'New Message From Example',
text: message,
html: `<p>${message}</p>`
},
json: true
};
const response = await new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) reject(error);
resolve(body);
});
});
sentMessages.push({
sender: user.name,
recipient: contact.name,
content: message,
messageId: response.message_ids[0] // Assuming there's only one message ID
});
}
return sentMessages;
}
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
//app.js
require("dotenv").config({ path: "./config/config.env" });
const express = require("express");
const morgan = require("morgan");
const connectDB = require("./config/db");
const auth = require("./middlewares/auth");
const messages = require("./message")
const app = express();
// middlewares
app.use(express.json());
app.use(morgan("tiny"));
app.use(require("cors")());
// routes
app.use("/api", require("./routes/auth"));
app.use("/api", require("./routes/contact"));
// server configurations.
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => {
connectDB();
console.log(`server listening on port: ${PORT}`);
});
I’ve been getting an error
SendMessages.js:15 User not found in AuthContext
[email protected]:
I tried adding isLoading state that is initially set to true. When the checkUserLoggedIn function is called, it sets isLoading to true before fetching the user data and sets it to false after the user data has been fetched. So, I can check the isLoading state in my components to determine whether the user data has been loaded.