有没有办法访问useEffect钩子中设置的useState方法?

问题描述 投票:0回答:1

我正在尝试从前端向接收者发送消息。根据后端,它工作得很好。但在前端,我很难在前端实现后端代码以向接收者发送消息。 我将借给你我的服务器端代码和客户端。

后端 消息.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.ja

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;

前端 登录.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;

reactjs node.js socket.io react-fullstack socket.io-client
1个回答
0
投票

您在 state/useState 中设置的 userId 的评论挂载后,您会得到什么?

© www.soinside.com 2019 - 2024. All rights reserved.