【问题标题】:useState not updating correctly with socket.iouseState 未使用 socket.io 正确更新
【发布时间】:2020-05-02 23:54:49
【问题描述】:

我正在通过 socket.io 提取数据,但是在侦听来自服务器的传入消息时,我的状态没有正确更新。

我可以看到数据正在从套接字中正确提取(50 个请求对等秒),但 setQuotes 只是用从服务器返回的新项目替换现有项目(所以我的状态总是长度为 1)。

  const [quotes, setQuotes] = useState([])
 const subscribe = () => {
    let getQuote = 'quote.subscribe';
    socket.emit(getQuote, {});
    socket.on('listenAction', function (msg) {
        setQuotes([...quotes, msg]) // This just replace the entire state instead of adding items to the existing array
    }); 
}

订阅 // 打开网络套接字流

【问题讨论】:

  • 你可以试试 setQuotes(oldQuotes => [...oldQuotes, msg]) 吗?
  • 你找到解决办法了吗,我也面临同样的问题?

标签: reactjs websocket socket.io react-hooks state


【解决方案1】:

您需要将侦听器移到订阅函数之外。 因为它是一个副作用,你应该把它包装在React.useEffect 使用函数 setstate 读取以前的值也是一个好主意。

React.useEffect(() => {
    socket.on('listenAction', function (msg) {
        setQuotes((quotes) => [...quotes, msg])
    }); 
}, []);

【讨论】:

    【解决方案2】:

    在您的示例中,您像这样使用 setState

    setQuotes([...quotes, msg])
    

    每次收到消息时,javascript 引擎都会尝试在此函数范围内查找“引号”变量

    function (msg) {
    

    这里找不到,移动到定义这个函数的作用域(组件函数的作用域)。

    对于每个函数调用,都有新的作用域。并为每个渲染调用组件函数。因此,您的函数在参数中使用“msg”,在其中使用 setQuotes,每次都使用第一次渲染时的“quotes”状态。

    在第一次渲染中,您有一个空数组。

    那么你有[...firstEmptyArray, firstMessage]

    那么你有[...firstEmptyArray, secondMessage]

    那么你有[...firstEmptyArray, thirdMessage].

    如果您将使用 setQuotes 之类的,您可能可以修复它;

    setQuotes(oldQuotes => [...oldQuotes, msg]);
    

    这样它将使用previousValue来计算新的。

    PS。请注意不要在每个渲染中直接调用您的订阅函数,并将其放入 useEffect 中,并使用正确的依赖数组作为第二个参数。

    【讨论】:

      【解决方案3】:

      你可以在这里使用 concat 函数
      setQuotes(prevState => prevState.concat(msg))

      【讨论】:

        猜你喜欢
        • 2021-10-05
        • 1970-01-01
        • 1970-01-01
        • 2023-01-05
        • 2020-12-28
        • 2021-01-15
        • 1970-01-01
        • 2021-03-15
        • 2021-04-15
        相关资源
        最近更新 更多