reactjs - 如何将前端 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;
解决方案
我认为您在客户端连接的方式不正确,您基本上是在连接到您的反应应用程序,您需要像这样将BACKEND URL传递给io
const socket = io('http://localhost:5000/', {
transports: ["websocket","polling"],
});
推荐阅读
- reactjs - 为什么从事件处理程序调用的函数被视为“回调”函数?(反应)
- php - 在 laravel 中的两个不同控制器之间传递数据
- sql-server - SQLCMD -g 选项
- php - 使用 PHP "include" 函数向页面添加第二个标题
- html - 如何在 iframe 中使用链接更改父页面
- micronaut - micronaut - 如何接受任何请求内容和正文
- .htaccess - 为合并到单个域的多个域设置 301 重定向
- java - 如何在获取值之前对 JSONObject 中的每个元素进行空值检查?
- python - 安装 Anaconda3 时创建菜单失败
- android - 从 Kotlin 的 Mapbox 获取我的位置 LatLng