具有React的SignalR不太实时

时间:2018-07-02 12:09:11

标签: reactjs signalr

我使用香草JavaScript跟随了this的SignalR教程,一切进展顺利。我打开了两个浏览器,一旦我从任何一个浏览器发送消息,两个浏览器都会立即更新。问题位于底部。

然后我在VS2017中启动了另一个项目,这次是一个使用aspnet core 2.1的React模板。在Startup.cs

中添加了signalr
services.AddMvc().SetCompa.....
services.AddSignalR(); // added this
services.AddSpaStaticFiles......

app.UseSpaStaticFiles();
// then added below code
app.UseSignalR(routes =>
{
    routes.MapHub<ChatHub>("/chathub");
});
app.UseMvc(.....

使用了这个chathub类

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

并尝试将原始JS代码转换为对此有反应的

....
this.state = { name: "", message: "", messages: [], hubConnection: null }
...
componentDidMount() {
    const connection = new SignalR.HubConnectionBuilder()
        .withUrl("/chathub")
        .build();
    connection.on("ReceiveMessage", (user, message) => this.receiveMessage(user, message))
    connection.start().catch(err => console.error(err.toString())); 
    this.setState({ hubConnection: connection });
}

receiveMessage = (user, message) => {
    let msgs = this.state.messages;
    const msg = message
      .replace("/&/g", "&amp;")
      .replace("/</g", "&lt;")
      .replace("/>/g", "&gt;");
    const encodedMsg = user + " says " + msg;
    msgs.push(encodedMsg);
}

sendMessage = async (event) => {
    event.preventDefault();
    let user = this.state.name;
    let message = this.state.message;
    let connection = this.state.hubConnection;
    await connection
      .invoke("SendMessage", user, message)
      .catch(err => console.error(err.toString()));
    this.setState({ name: "", message: "" });
}; 

然后在渲染器中添加了以下内容

<p>User: </p><input type="text" id="userInput" value={this.state.name} onChange={event => { this.setState({ name: event.target.value }); }} />
<p>Message: </p><input type="text" id="messageInput" value={this.state.message} onChange={event => { this.setState({ message: event.target.value }); }} />
<input type="button" id="sendButton" onClick={this.sendMessage} value="Send Message"/>

<ul>
    {this.state.messages.map(message => (
        <li key={message}>{message.toString()}</li>
    ))}
</ul>

然后将方法绑定到类。问题,其他浏览器发送消息时,其他浏览器没有立即更新。我需要执行一些操作以使其重新呈现,例如在输入字段中键入内容。那么,如何使它侦听传入的消息并在收到消息时重新呈现呢?我认为我的问题是我的客户代码不知道如何收听消息,除非它是明确调用SendMessage方法的人

1 个答案:

答案 0 :(得分:0)

对不起我。 msgs.push不会触发重新渲染,只是读到改变状态是不好的。所以我只对消息状态执行了concat来返回新值,将新消息推送到新数组,然后设置为setState

let arr = []
let msgs = this.state.messages.concat(arr);
......
msgs.push(encodedMsg);
this.setState({ messages: msgs });