微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何防止由于异步代码和 websocket 竞争条件而导致反应状态覆盖?

如何解决如何防止由于异步代码和 websocket 竞争条件而导致反应状态覆盖?

我正在构建一个使用 recoiljs 作为状态管理器的 React 应用程序,我需要从 Web 套接获取数据并相应地更新状态。我不使用常规数组的原因是我需要在我的组件之间共享状态。

详细来说,该组件有一个 WebSocket 连接,并将有数据流入其中。然后它需要通过推送接收到的数据来更新数组。问题是由于组件生命周期或其他原因,状态写入不正确,这就是我认为发生的情况

  1. 收到响应 1 并调用 setState([...state,data])
  2. 然后收到响应 2 并调用 setState([...state,data])
  3. 状态实际上是由响应 1 设置的
  4. 状态由响应 2 设置

问题是当响应 2 进入并调用 setState 时,它​​具有不包括响应 1 的旧版本状态。

我似乎不知道如何解决这个问题。这是精简后的代码

import {atom} from "recoil"
import {useRecoilState} from "recoil"
const WebSocket = require("isomorphic-ws");

const statusAtom = atom<string[]>({
    key: "statusAtom",default: []
});


function Component() {
    const [status,setStatus] = useRecoilState(statusAtom);

    const functionCalledAfterButtonPress = () => {
        ws.onmessage = function incoming(res: any) {
            console.log(res.data); // for debugging
            
            setStatus([...status,res.data]);
        };
    }
}

请注意,我不包括其他事件,例如 ws.onopen 和 return 语句或诸如此类的内容,并且原子声明和组件声明位于不同的文件中。

解决方法

正如 Jayce444 所说,解决这个问题的方法不是使用带有已计算值 setStatus[...status,res.data],而是传递一个 lambda 语句,该语句在状态更新时调用。

代替: setStatus([..status,res.data])

使用:setStatus(prevStatus => [...prevStatus,res.data])

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。