与 socket io 结合使用时,React Hook(usestate)不起作用

React Hook (usestate ) not working when combined with socket io

我快疯了。我真的不明白为什么下面的不起作用。我从反应开始。 我正在尝试从服务器获取 datas 并在渲染之前加载我的状态。 套接字“fromAPI”没问题,这只是一个计时器。 套接字“lobbyUpdate”不工作,我正在从数据库中获取数据。

import React, { useState, useEffect } from "react";
import socketIOClient from "socket.io-client";
const ENDPOINT = "http://localhost:2500";

function Lobby() {

    const [response, setResponse] = useState("")
    const [updates, setUpdates] = useState([])

    useEffect(() => {
        const socket = socketIOClient(ENDPOINT);

        socket.on("FromAPI", data => {
          setResponse(data);
        });

        socket.on('lobbyUpdate', datas => {
           console.log(updates) // Nothing 
           setUpdates(datas)

           console.log(datas) // datas are displayed
           console.log(updates) // nothing is displayed
          
        })
       
        // CLEAN UP THE EFFECT
        return () => socket.disconnect();
        //
      }, []);

console-capture

你能帮帮我吗?我没有找到类似的案例。 谢谢

您的代码运行良好,您只是将日志语句放在了无用的地方。

updates 是局部常量。它永远不会改变,这不是 setUpdates 想要做的。 useEffect 中的 console.log 语句只会引用 responseupdates 在第一次渲染时的值。

当您调用 setUpdates 时,您要求做出反应以重新呈现组件。在那个新渲染器上,将创建一个新的局部常量,并将获得新值。新渲染中的代码可以使用这个值,但以前渲染中的代码不能。如果您想验证它是否正在使用新值重新呈现,请将您的日志语句放入组件的主体中:

function Lobby() {

    const [response, setResponse] = useState("")
    const [updates, setUpdates] = useState([])

    console.log("rendering with: ", response, updates);

    useEffect(() => {
        const socket = socketIOClient(ENDPOINT);

        socket.on("FromAPI", data => {
          setResponse(data);
        });

        socket.on('lobbyUpdate', datas => {
           setUpdates(datas)
        })
       
        // CLEAN UP THE EFFECT
        return () => socket.disconnect();
    }, []);

useEffect 中的 updates 引用了 初始渲染 中的值,而不是当前正在渲染的值。要修复它,要么使用 refs 而不是(或除了)state,或者在每次更新更改时使用 useEffect 运行:

function Lobby() {
    const [response, setResponse] = useState("")
    const [updates, setUpdates] = useState([])
    const socketRef = useRef();
    // Create the socket
    // and add the API listener:
    useEffect(() => {
        socketRef.current = socketIOClient(ENDPOINT);
        socketRef.current.on("FromAPI", setResponse);
        return () => socketRef.current.disconnect();
    }, []);

    useEffect(() => {
        const handleLobbyUpdate =  (datas) => {
            console.log(updates); // this will now display the current data
            setUpdates(datas);
        };
        socketRef.current.on('lobbyUpdate', handleLobbyUpdate);
        return () => {
            socketRef.current.off('lobbyUpdate', handleLobbyUpdate);
        }
    }, [updates]);

请记住,状态设置器是异步的,因此您不会在调用 setUpdates 后立即看到 updates 变量发生变化 - 您必须等到下一次呈现 updates 成为人口。