使用仅添加一个元素的套接字更新 mui 数据网格
Update mui data-grid with socket only one element added
我在使用 mui 数据网格和 socket.io 时遇到问题。
我从 api 加载初始数据,效果很好。
但是当我想用来自 websocket 的数据更新 table 时,每次更改时只添加并覆盖一个元素。代码如下:
Table:
const [tableData, setTableData] = useState(props.tableData);
useEffect(() => {
setTableData(props.tableData);
}, [props.tableData]);
return (<div key="tradingTableGrid" style={{ height: 450, width: "100%" }}>
<DataGrid
key={"TradingTable"}
rows={Object.values(tableData)}
columns={tableHead}
rowHeight={30}
pageSize={10}
onRowClick={(row) => openModal(row)}
/>
</div>);
加载初始数据和调用 websocket 更新的组件如下(我只添加了必要的代码):
const [data, setData] = useState({});
const [loadData, setLoadData] = useState(false);
const [socketActive, setSocketActive] = useState(false);
// initial data loading from api
const handleResponse = (response) => {
var result = {};
response.forEach((prop) => {
result = {
...result,
[prop.order_id]: {
id: prop.order_id,
orderId: prop.order_id,
price: prop.price.toString(),
volume: prop.max_amount_currency_to_trade,
minVolume: prop.min_amount_currency_to_trade,
buyVolume: prop.max_volume_currency_to_pay + " €",
minBuyVolume: prop.min_volume_currency_to_pay + " €",
user: prop.trading_partner_information.username,
},
};
});
setData(result);
};
// add from websocket
const addOrder = (order) => {
if (
order.trading_pair === "btceur" &&
order.order_type === "buy" &&
(order.payment_option === "1" || order.payment_option === "3")
) {
if (typeof data[order.order_id] === "undefined") {
console.log(data);
setData({
...data,
[order.order_id]: {
id: order.order_id,
orderId: order.order_id,
price: order.price.toString(),
volume: order.amount,
minVolume: order.min_amount,
buyVolume: Number(order.volume).toFixed(2) + " €",
minBuyVolume: Number(order.min_amount * order.price).toFixed(2) + " €",
user: "not set through socket",
},
});
}
}
};
useEffect(() => {
const loadData = () => {
setLoadData(true);
axios
.get(process.env.REACT_APP_BITCOIN_SERVICE + "/order/book?type=buy")
.then((response) => handleResponse(response.data.orders))
.catch((exception) => console.error(exception))
.finally(() => setLoadData(false));
};
if (Object.keys(data).length === 0 && socketActive === false) {
loadData();
}
const socket = () => {
const websocket = io("https://ws-mig.bitcoin.de:443/market", {
path: "/socket.io/1",
});
websocket.on("connect", function () {
setSocketActive(true);
});
websocket.on("remove_order", function (order) {
removeOrder(order);
});
websocket.on("add_order", function (order) {
addOrder(order);
});
websocket.on("disconnect", function () {
setSocketActive(false);
});
};
if (socketActive === false && Object.keys(data).length !== 0) {
socket();
}
}, [data, socketActive]);
return (
<Table
tableHeaderColor="info"
tableHead={tableHead}
tableData={data}
type="buy"
/>
);
有谁知道为什么在通过套接字进行更新时只添加数据中的一个元素,而在每次下一次调用时都被覆盖?
问题
原因是套接字处理程序正在使用第一个渲染器中的状态设置器。
以 addOrder
为例,您在特定数据值的上下文中创建该函数,当您调用 setData({...data
时,它将始终使用数据的初始状态。 (要了解为什么请参阅来自 facebook 的 React 开发人员 Dan Abramov 的 How do JavaScript closures work? and also A Complete Guide to useEffect)
解决方案
您可以改为使用功能更新语法,让您将函数传递给 setData:
setData( data => ({...data,
这确保始终使用最后存储的值。
查看 useState 上的 React 文档 Functional updates
我在使用 mui 数据网格和 socket.io 时遇到问题。 我从 api 加载初始数据,效果很好。 但是当我想用来自 websocket 的数据更新 table 时,每次更改时只添加并覆盖一个元素。代码如下:
Table:
const [tableData, setTableData] = useState(props.tableData);
useEffect(() => {
setTableData(props.tableData);
}, [props.tableData]);
return (<div key="tradingTableGrid" style={{ height: 450, width: "100%" }}>
<DataGrid
key={"TradingTable"}
rows={Object.values(tableData)}
columns={tableHead}
rowHeight={30}
pageSize={10}
onRowClick={(row) => openModal(row)}
/>
</div>);
加载初始数据和调用 websocket 更新的组件如下(我只添加了必要的代码):
const [data, setData] = useState({});
const [loadData, setLoadData] = useState(false);
const [socketActive, setSocketActive] = useState(false);
// initial data loading from api
const handleResponse = (response) => {
var result = {};
response.forEach((prop) => {
result = {
...result,
[prop.order_id]: {
id: prop.order_id,
orderId: prop.order_id,
price: prop.price.toString(),
volume: prop.max_amount_currency_to_trade,
minVolume: prop.min_amount_currency_to_trade,
buyVolume: prop.max_volume_currency_to_pay + " €",
minBuyVolume: prop.min_volume_currency_to_pay + " €",
user: prop.trading_partner_information.username,
},
};
});
setData(result);
};
// add from websocket
const addOrder = (order) => {
if (
order.trading_pair === "btceur" &&
order.order_type === "buy" &&
(order.payment_option === "1" || order.payment_option === "3")
) {
if (typeof data[order.order_id] === "undefined") {
console.log(data);
setData({
...data,
[order.order_id]: {
id: order.order_id,
orderId: order.order_id,
price: order.price.toString(),
volume: order.amount,
minVolume: order.min_amount,
buyVolume: Number(order.volume).toFixed(2) + " €",
minBuyVolume: Number(order.min_amount * order.price).toFixed(2) + " €",
user: "not set through socket",
},
});
}
}
};
useEffect(() => {
const loadData = () => {
setLoadData(true);
axios
.get(process.env.REACT_APP_BITCOIN_SERVICE + "/order/book?type=buy")
.then((response) => handleResponse(response.data.orders))
.catch((exception) => console.error(exception))
.finally(() => setLoadData(false));
};
if (Object.keys(data).length === 0 && socketActive === false) {
loadData();
}
const socket = () => {
const websocket = io("https://ws-mig.bitcoin.de:443/market", {
path: "/socket.io/1",
});
websocket.on("connect", function () {
setSocketActive(true);
});
websocket.on("remove_order", function (order) {
removeOrder(order);
});
websocket.on("add_order", function (order) {
addOrder(order);
});
websocket.on("disconnect", function () {
setSocketActive(false);
});
};
if (socketActive === false && Object.keys(data).length !== 0) {
socket();
}
}, [data, socketActive]);
return (
<Table
tableHeaderColor="info"
tableHead={tableHead}
tableData={data}
type="buy"
/>
);
有谁知道为什么在通过套接字进行更新时只添加数据中的一个元素,而在每次下一次调用时都被覆盖?
问题
原因是套接字处理程序正在使用第一个渲染器中的状态设置器。
以 addOrder
为例,您在特定数据值的上下文中创建该函数,当您调用 setData({...data
时,它将始终使用数据的初始状态。 (要了解为什么请参阅来自 facebook 的 React 开发人员 Dan Abramov 的 How do JavaScript closures work? and also A Complete Guide to useEffect)
解决方案
您可以改为使用功能更新语法,让您将函数传递给 setData:
setData( data => ({...data,
这确保始终使用最后存储的值。
查看 useState 上的 React 文档 Functional updates