我正在尝试将Websocket与钩子一起使用,并在useEffect上启动它。但是状态始终是websocket的初始状态。
我知道发生这种情况是因为useEffect创建了一个闭包,但是我没有找到解决方法。
我简化了代码,使其易于理解。 我需要根据activeContracts做出决定,但它不会改变。 我尝试不将ws用作状态,但是在新的渲染中会丢失它。
function Bitstamp() {
const [activeContracts, setActiveContracts] = useState(["btcusd"]);
const [ws, setWs] = useState();
useEffect(
() => {
let newWs = new WebSocket("wss://ws.bitstamp.net");
newWs.onopen = function () {
activeContracts.map(contract => newWs.send({
"event": "bts:subscribe",
"data": {
"channel": "order_book_btcusd"
}
}));
};
newWs.onmessage = function (evt) {
console.log(activeContracts);
};
setWs(newWs);
},
[],
);
const handleContractChange = val => {
setActiveContracts(val);
};
return (
<ToggleButtonGroup vertical type="checkbox" value={activeContracts}
onChange={handleContractChange}>
<ToggleButton
value="btcusd">"btcusd"</ToggleButton>
)}
<ToggleButton
value="btceur">"btceur"</ToggleButton>
)}
</ToggleButtonGroup>
);
}
反正Websocket是否有通知状态变化? 我应该以其他方式初始化websocket还是不将其保持为状态?
更新:
我添加了一个useEffect跟踪activeContracts并更新onopen和onmessage并正常工作。像这样:
useEffect(
() => {
setWs(ws => {
ws.onopen = function () {
activeContracts.map(contract => newWs.send({
"event": "bts:subscribe",
"data": {
"channel": "order_book_btcusd"
}
}));
};
ws.onmessage = function (evt) {
console.log(activeContracts);
};
return ws;
})
},
[activeContracts],
);
答案 0 :(得分:0)
这是因为useState
在组件初始化时仅运行一次,这是因为array参数为空。您需要在该数组中跟踪activeContracts
,但是由于activeContracts
是数组本身,因此您需要为其使用某种深度比较功能:https://stackoverflow.com/a/54096391/4468021