Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 为什么我的WebSocket消息处理程序总是获取React state hook变量';什么是初始值?_Reactjs - Fatal编程技术网

Reactjs 为什么我的WebSocket消息处理程序总是获取React state hook变量';什么是初始值?

Reactjs 为什么我的WebSocket消息处理程序总是获取React state hook变量';什么是初始值?,reactjs,Reactjs,在我的App.js React功能组件中,我想创建一个用于与web服务器通信的WebSocket。它作为道具传递给一些子组件,以监听来自服务器的不同类型的更新。当套接字工作并且我的子组件获取所有消息时,消息处理程序对React.useState变量所做的任何更改都将在下次调用消息处理程序时消失 在下面的代码中,console.log始终为msgCount打印0,即使我在方法中增加它,并且我看到我从服务器收到1200条消息 export default function App(props) {

在我的App.js React功能组件中,我想创建一个用于与web服务器通信的WebSocket。它作为道具传递给一些子组件,以监听来自服务器的不同类型的更新。当套接字工作并且我的子组件获取所有消息时,消息处理程序对React.useState变量所做的任何更改都将在下次调用消息处理程序时消失

在下面的代码中,console.log始终为msgCount打印0,即使我在方法中增加它,并且我看到我从服务器收到1200条消息

export default function App(props) {
    const [webSocket, setWebSocket] = React.useState(null);
    const [msgCount, setMsgCount] = React.useState(0);

    function getWebSocket() {
        let ws = new WebSocket("ws://localhost:8083/");
        ws.onmessage = function (event) {
            console.log("msgCount=" + msgCount);
            setMsgCount(msgCount + 1);
        };
        return ws;
    }

    let ws = webSocket;
    if (ws === null && loggedInUser !== null) {
        ws = getWebSocket();
        setWebSocket(ws);
    }
    return (
        <div>Hello World</div>
    );
}
导出默认功能应用程序(道具){
const[webSocket,setWebSocket]=React.useState(null);
const[msgCount,setMsgCount]=React.useState(0);
函数getWebSocket(){
让ws=newwebsocket(“ws://localhost:8083/”;
ws.onmessage=函数(事件){
console.log(“msgCount=“+msgCount”);
设置msgCount(msgCount+1);
};
返回ws;
}
设ws=webSocket;
如果(ws==null&&loggedInUser!==null){
ws=getWebSocket();
setWebSocket(ws);
}
返回(
你好,世界
);
}

您不能在运行时更新websocket。你可以把它看作一枚火箭,当火箭发射到太空时,你无法改变它的建造方式。如果在启动时传递状态值,它将使用该值启动,并且不会更改它。它可以检测服务器上的更改并向前端发送消息,但无法从前端接收任何内容

这里的一个解决方法是停止websocket连接,并在每次需要更改值时重新初始化它,但我不建议这样做,除非确实有必要


如果您确实需要在运行时更改websocket的参数,我建议您在GitHub上查看一下。

尝试使用延迟形式的
setState
setX(prevX=>prevX+1)
。它不使用声明状态变量时的值,而是存储一个函数(
prevX=>prevX+1
),该函数在任何时候被调用时都会传递最新值

具体来说,在您的情况下,这可能看起来像

export default function App(props) {
    const [webSocket, setWebSocket] = React.useState(null);
    const [msgCount, setMsgCount] = React.useState(0);

    // this is here just for an accurate log statement; it triggers whenever `msgCount` is changed
    React.useEffect(() => {
       console.log("msgCount in effect:", msgCount);
    }, [msgCount])

    function getWebSocket() {
        let ws = new WebSocket("ws://localhost:8083/");
        ws.onmessage = function (event) {
            // This will still log 0 because `msgCount` is fixed here and never redefined
            console.log("msgCount in onmessage:", msgCount);
            // but this "deferred" form of `setState` updates the value based on its current value, so is not using `msgCount` in the current scope.
            setMsgCount(count => count + 1);
        };
        return ws;
    }

    let ws = webSocket;
    if (ws === null && loggedInUser !== null) {
        ws = getWebSocket();
        setWebSocket(ws);
    }
    return (
        <div>Hello World</div>
    );
}

但我并不是试图在运行时更改WebSocket,而是试图更改前端的状态。在本例中只是一个计数,但在实际应用程序中,来自服务器的消息需要存储在组件的数组中,以便render()方法可以显示它们。在本例中,它是WebSocket实际上并不重要。您只需调用一次
getWebSocket
(按设计)--之后
webSocket
,因此
ws
不是
null
,因此该函数不会再次被调用。因此,回调函数
ws.onevent
已经定义,并且与组件的状态无关
ws
可以是websocket,也可以是普通对象,结果是一样的。谢谢@AndrewSchwartz-也许我应该换一种方式问我的问题:如何将到达的消息绑定回组件的状态?需要显示通过套接字发送的当前和以前的消息的组件是如何做到这一点的?我需要使用全局变量吗?我不熟悉Javascript/React,所以如果这有一个明显的答案,高级道歉。警告:我对web套接字了解不多,但我想我可以在这里把它隐藏起来。我要考虑的一个方法是创建一个新文件,让我们说“代码> WebSoCKMealth.js<代码>。此文件将有一个类
WebSocketManager
,您将创建并导出该类的一个实例:
export const WebSocketManager=WebSocketManager.new()。此类可以保留名为
messageCount
的内部数据成员和
webSocket
。无论您在哪里
import{webSocketManager}
它都会引用同一个实例(您导出/导入的是实例,而不是类),因此共享值
message\u count
。实际上,我刚才研究的另一种方法更适合您实际尝试的操作。我将在下面发布。谢谢安德鲁-这实际上解决了我的问题。使用函数访问msgCount的当前值就达到了目的。
React.useEffect(() => {
    const ws = webSocket;
    if (ws === null && loggedInUser !== null) { ... }
}, [loggedInUser]);