在 React 中更改状态会导致 Azure SignalR 出现错误 429

Changing state in React causes error 429 with Azure SignalR

我正在尝试使用 this tutorial as a base. I haven't changed anything about the SignalR server, which can be found here 制作一个带有 Azure SignalR 的 React 应用程序。我正在使用 JS 版本。该应用程序在其他方面运行良好,但只要状态发生变化,请求就会发送到 SignalR 或类似的东西,最终导致 429 错误。这是状态改变一次时的输出:

[2020-01-09T15:11:42.207Z] Information: Normalizing '/api' to 'http://localhost:3000/api'.
[2020-01-09T15:11:42.437Z] Information: WebSocket connected to wss://bpm-drawing.service.signalr.net/client/?hub=chat&id=5_gylFnC52hduxXnoFT7dgb3b5d12b1&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE1Nzg1ODI3MDIsImV4cCI6MTU3ODU4NDUwMiwiaWF0IjoxNTc4NTgyNzAyLCJhdWQiOiJodHRwczovL2JwbS1kcmF3aW5nLnNlcnZpY2Uuc2lnbmFsci5uZXQvY2xpZW50Lz9odWI9Y2hhdCJ9.byfLiITpaUPm9OLxjn-EN8XcwDT3_j6tdoN2uSdR91k.
[2020-01-09T15:11:42.440Z] Information: Using HubProtocol 'json'.

足够多的后续状态更改会导致 429 错误。一些错误信息:

WebSocket connection to 'wss://bpm-drawing.service.signalr.net/client/?hub=chat&id=zer-1PBd58usOkZ2n-3Wuwb3b5d12b1&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE1Nzg1ODI4OTYsImV4cCI6MTU3ODU4NDY5NiwiaWF0IjoxNTc4NTgyODk2LCJhdWQiOiJodHRwczovL2JwbS1kcmF3aW5nLnNlcnZpY2Uuc2lnbmFsci5uZXQvY2xpZW50Lz9odWI9Y2hhdCJ9.t7HPErziiAbQX1PLONvtF3tSHa4ezcBNgAhb0tgNJYA' failed: Error during WebSocket handshake: Unexpected response code: 429
[2020-01-09T15:14:59.060Z] Error: Failed to start the transport 'WebSockets': Error: There was an error with the transport.
POST https://bpm-drawing.service.signalr.net/client/negotiate?hub=chat&negotiateVersion=1 429
[2020-01-09T15:14:59.143Z] Error: Failed to complete negotiation with the server: Error
[2020-01-09T15:14:59.148Z] Error: Failed to start the connection: Error
Errors.ts:20 Uncaught (in promise) Error
    at new HttpError (Errors.ts:20)
    at XMLHttpRequest.xhr.onload (XhrHttpClient.ts:70)

我精简了我的代码,但这足以导致错误:

import React from "react";
const signalR = require("@microsoft/signalr");

export const App = () => {
  const [message, setMessage] = React.useState("");
  const connection = new signalR.HubConnectionBuilder()
    .withUrl(`/api`)
    .configureLogging(signalR.LogLevel.Information)
    .build();
  connection.onclose(() => console.log("disconnected"));
  connection.start();

  function updateMsg(e) {
    e.preventDefault();
    setMessage(e.target.value);
  }

  return (
    <div>
      <form>
        <input
          type="text"
          placeholder="Type message here..."
          onChange={updateMsg}
        />
      </form>
    </div>
  );
};

export default App;

npm 服务器有很多

[HPM] POST /api/negotiate?negotiateVersion=1 -> http://localhost:7071

好吧,问题是每次状态更新时,App 内部的代码都是 运行,因此再次形成连接。仍然没有完全弄清楚如何解决它,但至少我知道原因是什么。

编辑:因为我被问到,解决方案是将连接的形成放在 'useEffect' 钩子中,这样它只有 运行 一次,当组件被安装时。