首页 > 解决方案 > 如何将前端 ReactJS 套接字客户端连接到服务器端套接字?

问题描述

在我的 MERN 应用程序中出现以下错误。

WebSocket connection to 'ws://localhost:3000/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established.

不知道如何让前端 ReactJS 端的套接字客户端连接到服务器套接字端。

服务器.js

import express from 'express';
import dotenv from 'dotenv';
import colors from 'colors';
import cors from 'cors';
import connectDB from './config/db.js';
import productRoutes from './routes/productRoutes.js';
import path from 'path';
import twilio from 'twilio';
const VoiceResponse = twilio.twiml.VoiceResponse;
// import { CompositionInstance } from 'twilio/lib/rest/video/v1/composition';
import { Server } from 'socket.io';

dotenv.config();

connectDB();

const app = express();
app.use(cors());

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.set('view engine', 'pug');
// app.set('views', path.join(__dirname, 'views'));
app.set('views', path.join(path.resolve(), 'views'));

app.use('/api/products', productRoutes);

app.get('/', (req, res) => {
  res.send('API is running');
});

app.post('/twilioCallback', async (req, res, next) => {
  const status = req.body.StatusCallbackEvent;
  io.emit('status-update', status);
  return res.status(200).send(status);
});

const PORT = process.env.PORT || 5000;

const server = app.listen(
  PORT,
  console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold)
);

const io = new Server(server);

io.on('connection', (socket) => {
  console.log('Socket connected!');
});

ProductScreen.js

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { Row, Col, Image, ListGroup, Card, Button } from 'react-bootstrap';
import Rating from '../components/Rating';
import io from 'socket.io-client';
import axios from 'axios';

const ProductScreen = ({ match }) => {
  const [product, setProduct] = useState({});

  const socket = io({ transports: ['websocket', 'polling'] });
  socket.on('status-update', function (call) {
    const stext = document.getElementById('statusText');
    stext.innerText = call;
    // let statusUpdate;

    // switch (status) {
    //   case 'composition-request':
    //     statusUpdate = 'Sent request for composition. ✉️';
    //     break;

    //   default:
    //     statusUpdate = status;
    //     break;
    // };
  });

  useEffect(() => {
    console.log('about to fetch product');
    const fetchProduct = async () => {
      console.log('Below is the id param waht the fuck is it?');
      console.log(match.params.id);
      const { data } = await axios.get(`http://localhost:5000/api/products/${match.params.id}`);

      setProduct(data);
    };
    fetchProduct();
  }, [match]);

  return (
    <>
      <Link className='btn btn-light my-3' to='/'>
        Go Back
      </Link>
      <Row>
        <Col md={6}>
          <Image src={product.image} alt={product.name} fluid />
        </Col>
        <Col md={3}>
          <ListGroup variant='flush'>
            <ListGroup.Item>
              <h3>{product.name}</h3>
            </ListGroup.Item>
            <ListGroup.Item>
              <Rating value={product.rating} text={`${product.numReviews} reviews`} />
            </ListGroup.Item>
            <ListGroup.Item>Price : {product.price}</ListGroup.Item>
            <ListGroup.Item>Description : {product.description}</ListGroup.Item>
          </ListGroup>
        </Col>
        <Col md={4}>
          <Card>
            <ListGroup variant='flush'>
              <ListGroup.Item>
                <Row>
                  <Col>Price: </Col>
                  <Col>
                    <strong>${product.price}</strong>
                  </Col>
                </Row>
              </ListGroup.Item>
            </ListGroup>
            <ListGroup variant='flush'>
              <ListGroup.Item>
                <Row>
                  <Col>Status: </Col>
                  <Col>{product.countInStock > 0 ? 'In Stock' : 'Out of Stock'}</Col>
                </Row>
              </ListGroup.Item>
              <ListGroup.Item>
                <Button
                  //   onClick={addToCartHandler}
                  className='btn-block w-100'
                  type='button'
                  disabled={product.countInStock === 0}
                >
                  Add To Cart
                </Button>
              </ListGroup.Item>
              <ListGroup.Item>
                <Row>
                  <Col>Copy Status: </Col>
                  <Col>
                    <product id='statusText'>null</product>
                  </Col>
                </Row>
              </ListGroup.Item>
            </ListGroup>
          </Card>
        </Col>
      </Row>
    </>
  );
};

export default ProductScreen;

标签: reactjsexpresswebsocketsocket.iomern

解决方案


我认为您在客户端连接的方式不正确,您基本上是在连接到您的反应应用程序,您需要像这样将BACKEND URL传递给io

 const socket = io('http://localhost:5000/', {
                transports: ["websocket","polling"],
            });

推荐阅读