SignalR 函数处理程序 React 不知道状态

问题描述 投票:0回答:1

我正在尝试了解 SignalR 的基础知识。我在 React 中创建了一个项目,在 asp.net core 6 中使用 Web api 创建了后端。在服务器端,我实现了 Hub 并从 React 连接到它。在客户端代码看起来像这样:

const [counter, setCounter] = useState(0);
const [connection, setConnection] = useState<HubConnection>();

const MyLog = (message: string) => {
console.log(message)
console.log(counter)
}

useEffect(() => {
connect();
  }, []);

const connect = async (): Promise<void> => {
    const connection = new HubConnectionBuilder()
      .withUrl(import.meta.env.VITE_SIGNALR)
      .configureLogging(LogLevel.Information)
      .build();

    connection.on("ReceiveMyMessage", (message) => {
      MyLog(message);
    });

    await connection.start();
    setConnection(connection);
};

所以基本上一切正常,当后端上的某种操作完成时,所有客户端上都会调用 MyLog(message) 函数,并且消息会被传递,这样就可以了。但是,正如您在代码中看到的,我还将此组件的计数器状态初始设置为 0。我还有一个按钮,用于在每次单击后将计数器状态增加 1。

它适用于客户端。所以我有新刷新的网站,计数器设置为 0 并且建立了 signalR 连接。然后我点击按钮 5 次,我可以在客户端日志中看到计数器状态为 5。但是当我从后端 MyLog 函数发送消息时,计数器的值为 0。换句话说,当我在反应组件中收到 SignalR 消息时,它不知道用户在浏览器中不断更新的组件的状态。

我做错了什么?

reactjs .net signalr asp.net-core-signalr
1个回答
0
投票

这是一个常见的 JavaScript 闭包问题,您可以使用

useRef
来修复它。

这是样本。

import React, { useState, useEffect, useRef } from 'react';
import { HubConnection, HubConnectionBuilder, LogLevel } from '@microsoft/signalr';

const TheTestComponent = () => {
  const [counter, setCounter] = useState(0);
  const [connection, setConnection] = useState<HubConnection>();
  const counterRef = useRef(counter); // Add useRef here

  // update the value of counter  in counterRef
  useEffect(() => {
    counterRef.current = counter;
    connect();
  }, [counter]);

  const MyLog = (message: string) => {
    console.log(message);
    console.log(counterRef.current); // save the latest value of counter in useRef 
  };

  useEffect(() => {
    const connect = async (): Promise<void> => {
      const newConnection = new HubConnectionBuilder()
        .withUrl(import.meta.env.VITE_SIGNALR)
        .configureLogging(LogLevel.Information)
        .build();

      newConnection.on("ReceiveMyMessage", (message) => {
        MyLog(message);
      });

      await newConnection.start();
      setConnection(newConnection);
    };

    connect();
  }, []);

  // ... 

  return (
    // ... 
  );
};

export default TheTestComponent;
© www.soinside.com 2019 - 2024. All rights reserved.