为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕妹3242003 2023-05-25 16:31:42
我要疯了。我真的不明白为什么下面的不起作用。我从反应开始。我正在尝试从服务器获取数据并在渲染之前加载我的状态。套接字“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();        //      }, []);你能帮帮我吗?我没有找到类似的案例。谢谢。
查看完整描述

3 回答

?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

您的updates内部正在引用初始 renderuseEffect的值,而不是当前正在呈现的值。要修复它,要么使用 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]);

请记住,状态设置器是异步的,因此您不会updates在调用后立即看到变量发生变化setUpdates- 您必须等到下一次渲染才能updates填充。


查看完整回答
反对 回复 2023-05-25
?
UYOU

TA贡献1878条经验 获得超4个赞

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


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


当您调用时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();

    }, []);


查看完整回答
反对 回复 2023-05-25
?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

您必须在 useEffect() 中定义套接字常量,它将在每次套接字更新后呈现 useEffect 挂钩。


const [update,setupdate] = useState()


useEffect(()=>{ 

const socket = io("http://localhost:3001");

socket.on("send data", function (data_from_socket) {

 setupdate(data_from_socket);

})

})

并且不要忘记不要在 useEfect 中使用 []


查看完整回答
反对 回复 2023-05-25
  • 3 回答
  • 0 关注
  • 235 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号