Click here to Skip to main content
15,887,267 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
I'm trying to send a message to the receiver from frontend. As per backend it worked fine. But in frontend I had a pretty hard time to implement the backend code in the frontend to send a message to the receiver. I'll lend you my server side code and client side.

What I have tried:

Backend message.js

const express = require('express');
const router = express.Router();
const fetchuser = require('../middleware/fetchuser');
const Message = require("../models/Message");



router.post('/sendmessages/:userId', fetchuser, async (req, res) => {
    const { receiver, text } = req.body;
    const sender = req.user._id;

    try {
        const message = new Message({ sender, receiver, text });
        await message.save();

        res.json(message);
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: 'Server error' });
    }
});

// Get messages for a specific user


module.exports = router;


auth.js

const express = require('express');
const router = express.Router();
const User = require('../models/User');
const bcrypt = require('bcrypt');
const { body, validationResult } = require('express-validator');
const jwt = require("jsonwebtoken");
const JWT_SECRET = 'INFAMOUS';
const fetchuser = require('../middleware/fetchuser');

router.post('/signup', [
  body('email').isEmail(),
  body('password', 'Password should be atleast 6 characters').isLength({ min: 6 })
], async (req, res) => {

  // If errors are found then this block will run
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  // define user data 
  const { email, password } = req.body;
  const salt = await bcrypt.genSalt(10);
  const secPass = await bcrypt.hash(password, salt);

  // Extract user data from models
  try {
    // Check email
    const user = await User.findOne({ email });
    if (user) {
      return res.status(400).json({ message: 'A user already exists with this e-mail address' });
    };
    const newUser = new User({
      email, password: secPass,
    });

    // Save user to db
    await newUser.save();

    const token = jwt.sign({userId:newUser._id}, JWT_SECRET);
    // save user token
    newUser.token = token;

    res.status(201).json({ token, message: "Succssfully user created" });

  } catch (error) {
    console.log(error);
    res.status(500).json({ message: "Internal server error" });
  }

});


router.post('/login',[
  body('email').isEmail(),
  body('password', 'No Blank').exists()
], async(req, res)=> {

  let success = false;
  // If errors are found then this block will run
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  // define user data 
  const { email, password } = req.body;
  try {
    // Check email
    const user = await User.findOne({ email });
    if (!user) {
      success = false;
      return res.status(400).json({success, message: 'Not found user' });
    };

    const compare = await bcrypt.compare(password, user.password);
    if(!compare) {
      success = false;
      return res.status(400).json({success, error: "Enter corretly"});
    }

    const token = jwt.sign({userId: user._id}, JWT_SECRET);
    success = true;
    res.status(201).json({ success, token, message: "Succssfully loginn" });

  } catch (error) {
    console.log(error);
    res.status(500).json({ message: "Internal server error" });
  }

})

router.post('/getuser', fetchuser,  async (req, res) => {

  try {
    const userId = req.user._id;
    const user = await User.findById(userId).select("-password");
    res.send(user);
  } catch (error) {
    console.error(error.message);
    res.status(500).send("Internal Server Error");
  }
})

router.get('/allusers' , async (req, res) => {
  await User.find({})
    .then(users => {
      const userFunction = users.map(user => {
        const container = {}
        container.email = user.email
        // container.role = user.role
        return container
      })
      res.status(200).json({ user: userFunction })
    })
    .catch(err =>
      res.status(401).json({ message: "Not successful", error: err.message })
    )
})

router.post('/logout', async(req,res)=>{
    try{
        res.clearCookie('token');
        res.status(200).json({success: true, message: 'Logout successfull'})
    } catch (error) {
        console.error(error);
        res.status(500).json({success: false, message: 'Internal server error'});
    }
})


module.exports = router


index.js

const express = require('express');
const db = require('./db');
const cors = require('cors');
const socketio = require('socket.io');

const app = express();
const http = require('http');
const server = http.createServer(app);
const io = socketio(server, {
  cors: {
    origin: 'http://localhost:3000',
    methods: ['GET', 'POST'],
  },
});

const port = 5000;

// Initiate MongoDB
db();

// JSON middleware
app.use(cors());
app.use(express.json());

// Accessing routers
app.use('/api/auth', require('./routes/auth'));
app.use('/api/message', require('./routes/message'));

// Socket.io setup
io.on('connection', (socket) => {
  console.log(`User connected: ${socket.id}`);

  // Listen for the "message" event from the client
  socket.on('message', (data) => {
    console.log(`New message from ${socket.id}: ${data}`);
  });

  // Listen for the "sendMessage" event from the client
  socket.on('sendMessage', (data) => {
    // Broadcast the message to all connected clients
    io.emit('message', data);
  });

  socket.on('disconnect', () => {
    console.log('User disconnected');
  });
});

server.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});


fetchuser.js

const jwt = require("jsonwebtoken");
const JWT_SECRET = 'INFAMOUS';

const fetchuser = (req, res, next) => {
    // Get the user from the jwt token and add id to req object
    const token = req.header('auth-token');
    if (!token) {
        return res.status(401).send({ error: "Please authenticate using a valid token" })
    }
    try {
        const data = jwt.verify(token, JWT_SECRET);
        console.log('Decoded Token:', data);
        req.user = { _id: data.userId };
        next();
    } catch (error) {
        return res.status(401).send({ error: "Please authenticate using a valid token" })
    }

}


module.exports = fetchuser;


Frontend Login.js

import axios from 'axios';
import React, {useState} from 'react'
import { useNavigate } from 'react-router-dom'

const Login = () => {
    const [credentials, setCredentials] = useState({email: "", password: ""}) 
    let navigate = useNavigate();

    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            const response = await axios.post("http://localhost:5000/api/auth/login", {
                email: credentials.email,
                password: credentials.password
            });
    
            const json = response.data
            console.log(json);
    
            if (json.success){
                // Save the auth token and redirect
                sessionStorage.setItem('token', json.token); 
                navigate("/");
            }
            else{
                alert("Invalid credentials");
            }
        } catch (error) {
            console.error('Login failed:', error);
        }
    }

    const onChange = (e)=>{
        setCredentials({...credentials, [e.target.name]: e.target.value})
    }
    return (
        <div>
            <form onSubmit={handleSubmit}>
                <div className="mb-3">
                    <label htmlFor="exampleInputEmail1" className="form-label">Email address</label>
                    <input type="email" className="form-control" name="email" value={credentials.email} onChange={onChange} id="email" aria-describedby="emailHelp"/>
                        <div id="emailHelp" className="form-text">We'll never share your email with anyone else.</div>
                </div>
                <div className="mb-3">
                    <label htmlFor="exampleInputPassword1" className="form-label">Password</label>
                    <input type="password" className="form-control" name="password" value={credentials.password} onChange={onChange} id="password"/>
                </div>
                <button type="submit" className="btn btn-primary">Submit</button>
            </form>
        </div>
    )
}

export default Login


Chat.js

import axios from 'axios';
import React, { useState, useEffect } from 'react';
import io from 'socket.io-client';

const socket = io('http://localhost:5000');

const Chat = () => {
  const [text, setText] = useState('');
  const [messages, setMessages] = useState([]);
  const [receiverOptions, setReceiverOptions] = useState([]);
  const [receiver, setReceiver] = useState('');
  const [senderUserId, setSenderUserId] = useState('');

  useEffect(() => {
    const fetchData = async () => {
      try {
        const authToken = sessionStorage.getItem('token');
        console.log('Auth Token:', authToken);

        if (authToken) {
          const response = await axios.post('http://localhost:5000/api/auth/getuser', null, {
            headers: {
              'auth-token': `Bearer ${authToken}`
            }
          });
          const userId = response.data._id;
          setSenderUserId(userId);
        }

        const usersResponse = await axios.get('http://localhost:5000/api/auth/allusers');
        setReceiverOptions(usersResponse.data.user);
      } catch (error) {
        console.error('Error fetching user or users:', error);
      }
    };

    fetchData();
  }, []);

  useEffect(() => {
    if (senderUserId) {
      socket.on('message', (message) => {
        setMessages((prevMessages) => [...prevMessages, message]);
      });
    }
  }, [senderUserId]);

  const handleSubmit = async (event) => {
    event.preventDefault();

    try {
      if (!senderUserId) {
        console.error('Sender User ID is empty or undefined.');
        return;
      }

      const response = await axios.post(`http://localhost:5000/api/message/sendmessages/${senderUserId}`, {
        receiver,
        text
      }, {
        headers: {
          'auth-token': `Bearer ${sessionStorage.getItem('token')}`
        }
      });

      const json = response.data;
      console.log('Message sent successfully:', json);

      socket.emit('sendMessage', {
        sender: senderUserId,
        receiver,
        text,
      });

      setText('');
    } catch (error) {
      console.error('Error sending message:', error);
    }
  };

  return (
    <>
      <div>
        <form onSubmit={handleSubmit}>
          <select value={receiver} onChange={(event) => setReceiver(event.target.value)}>
            <option value="" disabled>Select a user</option>
            {receiverOptions.map((user) => (
              <option key={user.email} value={user._id}>{user.email}</option>
            ))}
          </select>
          <input type="text" value={text} placeholder="Your message" onChange={(event) => setText(event.target.value)} />
          <button type="submit">Send</button>
        </form>
        <ul>
          {messages.map((message, index) => (
            <li key={index}>
              {message.receiver}: {message.text}
            </li>
          ))}
        </ul>
      </div>
    </>
  );
};

export default Chat;
Posted
Updated 8-Jan-24 6:38am
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900