【问题标题】:Socket.io resets React state?Socket.io 重置 React 状态?
【发布时间】:2018-10-11 19:07:28
【问题描述】:

我在使用 React 和 Socket.io 时遇到了一个奇怪的问题。感谢任何可以提供帮助的人。

目标:
-->1。 socket.io 发出一个事件来响应前端的按钮列表
-->2。 react 渲染按钮列表
-->3。用户点击按钮
-->4。按钮上的文本作为消息发送
-->5。将状态从 {hidden: false} 设置为 {hidden: true}
-->6。按钮被隐藏,因此用户无法返回并单击它们

代码:

import React, { Component } from 'react';
import uuidv4 from 'uuid';

class ButtonsMessage extends Component {
    constructor(props) {
        super(props);

        this.state = {
            hidden:false
        };

    }

    handleButtonClick = (event) => {
        this.setState({hidden:true});
        this.props.socket.emit('newMessage', event.target.textContent, this.props.user);
    };

    render() {
        const buttons = this.props.buttons;
        return (
            <li className="message w-100">
                {!this.state.hidden &&
                <div className="row justify-content-center message-content-wrapper">
                    <div className="col-8 message rounded message__body">
                        {
                            buttons.map((button) => {
                                return (
                                    <div
                                        key={uuidv4()}
                                        onClick={this.handleButtonClick}
                                        className="btn btn-outline-primary btn-sm message-btn">
                                        {button.buttonText}
                                    </div>
                                );
                            })
                        }
                    </div>
                </div>
                }
            </li>
        );
    }
}

export default ButtonsMessage;

问题:
步骤 1-4 工作正常。但是在用户单击一个按钮后,按钮不会被隐藏。当我在单击按钮后检查状态(在反应开发工具中)时,状态仍然是 {hidden:false}.React state screenshot 我怀疑在 this.props.socket.emit 之后状态会重置为原始状态线路运行。

疑难解答:
1. 在 socket.emit 之后移动 setState:不起作用
2. 注释掉 socket.emit 行:隐藏按钮
3.在setState中添加回调:

this.setState({hidden:true}, ()=>{
    console.log(this.state.hidden);
});

输出:

是的

我只包括我认为相关的代码。如果我需要发布代码的其他部分以帮助排除故障,请告诉我。

谢谢!

【问题讨论】:

  • 您发布的代码看起来不错。你能展示呈现这个的组件吗?也许由于某种原因它正在安装/卸载?你在更高的地方有套接字监听器吗?
  • 我能想象的唯一场景是重新安装完整的组件。尝试将日志条目添加到onComponentWillUnmount
  • 哦。有没有错误?也许socket.emit 会抛出一个停止 JS 执行的错误?
  • @azium 是的,这就是问题所在!我正在使用 uuidv4() 为渲染这个的组件生成一个唯一键。做了一些挖掘,发现这会导致每次组件渲染时都会重新生成密钥,这将导致重新安装子组件。感谢您为我指明正确的方向!
  • @JonasW。是的,这就是问题所在!请参阅下面我自己的答案。感谢您为我指明正确的方向!

标签: javascript reactjs socket.io


【解决方案1】:

原来我正在使用 uuidv4() 为渲染这个的组件生成一个唯一键。

...

return (
  <div key={uuidv4()}>
      {message.buttons && <ButtonsMessage socket={this.props.socket} user={this.props.user} buttons={message.buttons} />}
  </div>
)
...

做了一些挖掘,发现这会导致每次组件渲染时都会重新生成密钥,这将导致重新挂载子组件,从而重置其状态。

我将密钥生成移至 socket.io 服务器端并将该密钥作为唯一密钥传递给组件并修复了问题。

<div key={message.messageId}>
    {message.buttons && <ButtonsMessage socket={this.props.socket} user={this.props.user} buttons={message.buttons} />}
</div>

感谢所有帮助过的人!

【讨论】:

    猜你喜欢
    • 2021-07-25
    • 2020-11-28
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    相关资源
    最近更新 更多