useEffect内的状态不变

时间:2019-07-24 12:41:41

标签: reactjs react-hooks

我正在尝试将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],
);

1 个答案:

答案 0 :(得分:0)

这是因为useState在组件初始化时仅运行一次,这是因为array参数为空。您需要在该数组中跟踪activeContracts,但是由于activeContracts是数组本身,因此您需要为其使用某种深度比较功能:https://stackoverflow.com/a/54096391/4468021