React Hook+ Node.js 引入的Socket 聊天功能

3 篇文章 0 订阅
1 篇文章 0 订阅

后端:Node + Express

效果图:
在这里插入图片描述
在这里插入图片描述

1.基本写法:

安装:

npm install socket.io

值得注意的是,安装完这个后估计还有其他依赖的包会提醒需要安装,跟着提示走全都安装完即可。

const  express = require('express');

var app = express();
var server = app.listen(3010);
var io = require('socket.io').listen(server);

io.on('connection', function(socket){
	console.log('用户已经连接');
  
	socket.on('disconnect', function(){
	  console.log('用户已经离开');
	});
	
	//留意on和emit的方法名和前端保持一致  
	socket.on('sendMsgToServer', function(msgObj){
	  console.log('用户'+ msgObj.user + '说:'+ msgObj.msg);
	  io.emit('recvMsgFromServer', msgObj);
	});
  
});

2.问题处理

node.js控制台显示一致有访问请求连接:

GET /socket.io/?EIO=3&transport=polling&t=MLaWYlC 404 

原因可能是需要定义监听的接口,否则前端访问不到,会一直发起请求。(个人是这样解决 的,有问题望指正修改)

var server = app.listen(3010);
var io = require('socket.io').listen(server); //关键,监听3010端口

前端:React Hook

1.基本写法:

安装socket:

npm i socket.io-client --save
//创建socket连接,http使用ws协议,https使用wss协议
import io from 'socket.io-client'
const socket = io('ws://www.luojiework.cn:3010');

//监听/接收消息 从服务端接收
socket.on('recvMsgFromServer',function(data){
    addMsg(data);   // 聊天框添加消息的一个方法 
})

//发送消息 发送到服务端
socket.emit('sendMsgToServer',{
    msg: msg,
    user: user
});
2.问题处理

2.1 重复接收后端请求,即便前端只emit了一次消息,后端也on 了一次
定位问题在于socket.io的监听事件接收多次,也就是前端的

//监听/接收消息 从服务端接收
socket.on('recvMsgFromServer',function(data){
    addMsg(data);   // 聊天框添加消息的一个方法 
})

多次注册。

后来看了代码,我是将这段注册代码放在了console.log("你好")这个位置,实际运行的时候我们可以知道:
在这里插入图片描述
在这里插入图片描述
这里会多次触发的更新,也就是同时会注册多次socket监听,我们希望每个生命周期里只能有一个socket on,所以我用了两种方式:

①在组件销毁的时候关闭socket
也就是在hook组件销毁的生命周期里面加入socket.close();
要用到Effect hook,Effect hook的第一个参数可以return一个函数,这样就可以在组件销毁的时候触发它:

useEffect(() => {
    mounteMy();
    return closeSocket;
}, []);

const mounteMy = () => {
    console.log("触发mounteMy");
    socket.on('recvMsgFromServer',function(data){
        addMsg(data);   // 本地添加 
    })
    
}

const closeSocket = () => {
    console.log("关闭Socket");
    socket.close();
}

②同时我要保证只是socket on 一次

useEffect 有个问题,默认情况下,它在第一次渲染之后和每次更新之后都会执行。React 保证了每次运行 effect 的同时,DOM 都已经更新完毕。

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新

如果某些特定值在两次重渲染之间没有发生变化,你可以通知 React 跳过对 effect 的调用,只要传递数组作为 useEffect 的第二个可选参数即可。想达到componentDidMout的效果,第二个参数设置[],如果未设置第二个参数,而且在内部改变了状态,就会一直重复渲染

②useEffect没有更新
一开始我在下面这行代码里是这么写的(没用useRef)

addMsg(data);   // 本地添加 
//添加消息
const addMsg = (msgObj) => {

*****************省略
	//本地添加消息,对象数组增加新元素操作
   setMsgArr([
       ...msgArr,
       msgObj
   ])

*******************省略
}

但是我发现每次输出的永远是useState时候的值,很疑惑?

const [msgArr, setMsgArr] = useState([]); //值被定格在了这里

于是想着应该和useEffect里面调用方法有关。

虽然上面我们用useEffect模拟了componentDidMount生命周期—— useEffect(fn, []),但它们并不完全相等。和 componentDidMount 不一样,useEffect 会捕获 props 和state。所以即便在回调函数里,你拿到的还是初始的 props 和 state。

如果你想得到“最新”的值,你可以使用 ref。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值