node.js - 如何在 React 中显示组件并在每次显示时更新其生命周期?

标签 node.js reactjs express socket.io

我刚刚启动了node.js并做出了 react ,我很好奇如何使用socket.io创建一个聊天应用程序,所以我学习了一些关于如何创建房间、加入/离开以及在房间中发送消息的教程。我使用 React Context 来传递一个套接字实例。

我可以创建房间、加入房间、离开房间。我遇到的问题是,当我加入另一个房间并尝试发送消息时,我收到此警告:

Can't perform a React state update on an unmounted component. when rendering a component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

您能否给我一些建议,告诉我应该如何重新考虑在这种情况下使用 componentDidMountcomponentWillUnmount 函数重写 React?

我想添加这些详细信息以了解我想要做什么: - 用户可以创建房间的主页 - 房间生成为 2 个按钮,1 个用于显示聊天室(加入房间),另一个用于关闭聊天室(离开房间) - 用户可以加入聊天室并发送消息

客户端(Home.js)

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

  this.state = {
   room: "",
   rooms: [],
   chat: false
  };

  this.creatingRoom = this.creatingRoom.bind(this);
  this.joinRoom = this.joinRoom.bind(this);
  this.leaveRoom = this.leaveRoom.bind(this);

  this.props.socket.on("createRoom", function(room) {
   addRoom(room);
  });

  const addRoom = room => {
   this.setState({ rooms: [...this.state.rooms, room] });
  };
 };

 creatingRoom(e) {
  e.preventDefault();
  this.props.socket.emit("creatingRoom", {
   room: this.state.room
  });

  this.setState({ room: "" });
 };

 joinRoom(e) {
  let room = e.target.value;
  this.props.socket.emit("joinRoom", room);

  this.setState({
   chat: true
  });
 };

 leaveRoom(e) {
  let room = e.target.value;
  this.props.socket.emit("leaveRoom", room);

  this.setState({
   chat: false
  });
 };

 render() {
  return (

   <React.Fragment>

    {this.state.chat === true ? (
      <ChatroomWithSocket />
    ) : (
      <h1> no chatroom </h1>
    )}

    <div>
      <h1> Create your room </h1>
    </div>

    <div>
      <form>
        <textarea
          name="room"
          placeholder="Write.."
          value={this.state.room}
          onChange={ev => this.setState({ room: ev.target.value })}
        />
        <button onClick={this.creatingRoom}>
          Create
        </button>
      </form>
    </div>

    <div>
      <h4> Rooms </h4>
      <div>
        <ul>
          {this.state.rooms.map((room, index) => {
            return (
              <li key={index}>
                <button href="#" onClick={this.joinRoom} value={room.room}>
                  Join {room.room}
                </button>
                <button href="#" onClick={this.leaveRoom} value= 
                 {room.room}>
                  Leave {room.room}
                </button>
              </li>
            );
          })}
        </ul>
      </div>
    </div>

   </React.Fragment>
  );
 }
}

const HomeWithSocket = props => (
 <SocketContext.Consumer>
  {socket => <Home {...props} socket={socket} />}
 </SocketContext.Consumer>
);

客户端(Chatroom.js)

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

 this.state = {
  message: "",
  messages: []
 };

 this.sendMessage = this.sendMessage.bind(this);

 this.props.socket.on("receiveMessage", function(data) {
  addMessage(data);
 });

 const addMessage = data => {
  this.setState({ messages: [...this.state.messages, data] });
 };
}

  sendMessage(e) {
   e.preventDefault();
   this.props.socket.emit("sendMessage", {
   message: this.state.message
   });

   this.setState({ message: "" });
  }

render() {
 return (
  <React.Fragment>
    <div className="messages">
      {this.state.messages.map((message, key) => {
        return <li key={key}>{message.message}</li>;
      })}
    </div>

    <div>
      <form onSubmit={this.sendMessage}>
        <input
          type="text"
          placeholder="Message"
          value={this.state.message}
          onChange={ev => this.setState({ message: ev.target.value })}
        />
        <button type="submit"> 
          Send
        </button>
      </form>
    </div>
   </React.Fragment>
  );
 }
}

const ChatroomWithSocket = props => (
 <SocketContext.Consumer>
  {socket => <Chatroom {...props} socket={socket} />}
 </SocketContext.Consumer>
);

服务器端(index.js)

var rooms = [];

io.on("connection", function(socket) {

 socket.on("creatingRoom", function(room) {
  rooms.push(room);
  io.emit("createRoom", room);
 });

 socket.on("joinRoom", function(newRoom) {
  socket.join(newRoom);
  socket.room = newRoom;
 });

 socket.on("leaveRoom", function() {
  socket.leave(socket.room);
 });

 socket.on("sendMessage", function(data) {
  io.emit("receiveMessage", data);
 });
});

最佳答案

此错误通常意味着可能存在内存泄漏。

根据我的怀疑,它可能来自套接字连接。这样看..

componentDidMount中,您设置了一个套接字连接。如果您在未关闭套接字连接的情况下离开该组件,您一定会收到此错误。我不确定您到底在做什么,但请尝试关闭 componentWillUnmount 中的套接字以查看它是否有效。

如果是,请考虑在导航时不会被破坏的组件中创建套接字,或将套接字连接存储在 Redux 中

关于node.js - 如何在 React 中显示组件并在每次显示时更新其生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54675955/

相关文章:

javascript - 找不到\node_modules\@tensorflow\tfjs-node\lib\napi-v4\tfjs_binding.node

node.js - 使用 OAuth 时的 Google 日历 "The request is missing a valid API key"

mysql - NodeJS session 、cookie 和 mysql

reactjs - 在哪里调用 setState 来获取 redux 值?

node.js - 永远监控抛出 ENOENT 并且不工作

events - socket.io - 捕获所有事件

javascript - 我不知道如何正确地将 REST 响应对象传递给 ReactJS 子组件

javascript - 在 react js中展开一个数组

javascript - 尝试将 $set 与 stringify 一起使用,但它不起作用

node.js - 如何在 .ejs 文件中获取 Expreejs 的 req 和 res 对象