javascript - 当在 useEffect() 中触发 socket.on() 时,反应状态被设置回初始 []
问题描述
我是 React 功能组件的菜鸟,这是我第一次尝试使用 socket-io。
我有一个功能组件,它是一个收件箱,每页从InboxList
数组中呈现多达十个“警报”行。我正在使用 socket-io,以便在单击特定行时多个客户端可以实时查看(该行变为灰色)。
问题是大多数情况下,一旦单击警报,客户端(观察行更改,而不是单击)将收件箱为空(InboxList 中的 0 个警报)。
经过一些调试,我发现一旦触发了 socket.on('alertClicked'),我的 inboxList 状态就是空的(而不是我期望的相同的 10 个警报)。
这将导致我的inboxListCopy
内部greyOutAlert()
当然是空的。
如果有人有建议,将不胜感激。
上下文的功能组件代码:
import React, { useState, useContext, useEffect } from 'react';
import io from 'socket.io-client';
import Axios from 'axios';
import Table from 'react-bootstrap/Table';
import Pagination from 'react-responsive-pagination';
import { useHistory } from 'react-router-dom';
import '../../App.css';
let socket;
export default function Inbox() {
const [token, setToken] = useState(() => {
return localStorage.getItem('auth-token');
});
const [currentPage, setCurrentPage] = useState(() => {
return 1;
});
const [alertCount, setAlertCount] = useState(() => {
return 5;
});
const [inboxList, setInboxList] = useState(() => {
return [];
});
const history = useHistory();
useEffect(() => {
const connectionOptions = {
"force new connection" : true,
"reconnectionAttempts": "Infinity",
"timeout" : 10000,
"transports" : ["websocket"]
}
socket = io('http://localhost:5000', connectionOptions);
return () => {
socket.emit('disconnected');
socket.off();
}
}, []);
useEffect(()=>{
fetchAlertCount();
},[])
useEffect(()=>{
socket.on('alertClicked', (alertId) => {
greyOutAlert(alertId);
});
},[])
const greyOutAlert = (alertId) => {
let inboxListCopy = [...inboxList];
for (let i = 0; i < inboxListCopy.length; i++) {
if (inboxListCopy[i]._id === alertId) {
inboxListCopy[i].hasBeenReviewed = true;
break;
}
}
setInboxList(inboxListCopy);
};
useEffect(() => {
fetchAlerts();
},[currentPage]);
const fetchAlertCount = async () => {
const config = {
headers: {
'x-auth-token': token,
}
};
const alertCountResponse = await Axios.get('http://localhost:5000/alertinbox/totalAlerts', config);
setAlertCount(alertCountResponse.data.count);
};
const fetchAlerts = async () => {
const config = {
headers: {
'x-auth-token': token,
'page': currentPage
}
};
const alertsResponse = await Axios.get('http://localhost:5000/alertinbox/', config);
setInboxList(alertsResponse.data.alerts);
};
const handleClick = (alertId, messageType) => {
socket.emit('clientClickedAlert', {alertId});
switch (messageType) {
case '2+ Minutes':
history.push(`/2plusminutes/${alertId}`, {alertId});
break;
case 'SOS':
history.push(`/sos/${alertId}`, {alertId});
break;
case 'Low Battery':
history.push(`/lowbattery/${alertId}`, {alertId});
break;
};
};
return (
<React.Fragment>
<div id='inbox'>
<Table>
<thead>
<tr>
<th>Alert Type</th>
<th>Customer Name</th>
<th>Timestamp</th>
<th>Vehicle</th>
</tr>
</thead>
<tbody>
{inboxList.map(function(alert, index){
return(
<tr key={index} onClick={() => handleClick(alert._id, alert.messageType)} className={alert.hasBeenReviewed ? 'darken' : 'lighten'}>
<td>{alert.messageType}</td>
<td>{alert.ownerName}</td>
<td>{alert.createdAt}</td>
<td>{alert.vehicle.year + ' ' + alert.vehicle.make + ' ' + alert.vehicle.model}</td>
</tr>
)
})}
</tbody>
</Table>
</div>
<Pagination
current={currentPage}
total={Math.ceil(alertCount/10)}
onPageChange={setCurrentPage}
maxWidth={100}
/>
</React.Fragment>
)
}
解决方案
我建议您将确切的初始状态传递给 useState 挂钩,而不是像下面这样的函数:
const [inboxList, setInboxList] = useState([]);
推荐阅读
- javascript - AngularJS 路由 - $routeProvider 动态获取参数
- jquery - 下拉菜单 Jquery html
- c# - 如何在 MVVM 中更改 SelectedIndex
- osgi - Spring DM osgi 感知应用程序上下文中基于注释的 bean 配置
- python-3.x - python 3.0中字符串的减法和加法
- php - 在 Wordpress 中重置后元
- react-native - SectionList 获取 renderSectionHeader 中的节索引
- python - 在 Scrapy 中使用 CSS 和 Xpath 选择器
- c++ - 用于使 .EXE 不被标记为恶意软件的 C/C++ 混淆器
- asp.net - 当前不会命中断点 - 没有与此行关联的可执行代码