ReactJS和Websockets:监听服务器广播在前端

时间:2019-02-06 10:34:07

标签: javascript node.js reactjs redux websocket

我正在使用ReactJS, Socket.io, and NodeJS编写聊天应用程序。我已经完成了基本的套接字连接部分,当我输入一条消息并按Enter时,该消息将发送到后端。现在,我希望任何人添加一条消息(多个选项卡)后,该消息都将广播到所有其他客户端,但发起该消息的客户端除外,并应显示在消息列表中。当接收到来自特定客户端的消息时,我正在将消息从服​​务器广播到所有客户端,但是不确定在React应用程序的前端在哪里捕获它。

让我看一下代码:

App.js -我的应用程序包含3个主要组件,即Users(用户列表),Messages(消息列表,其中将显示所有在线用户的所有消息)和AddMessage(包含,文本框和按钮)添加一条消息)

class App extends Component {
  render() {
    const { classes } = this.props;
    return (
      <div className="App">
        {/* <UserNameInp /> */}
        <section className={classes.usersSection}>
          <Users />
        </section>
        <section className={classes.messagesSection}>
          <section className={classes.messagesStyle}>
            <Messages />
          </section>
          <section className={classes.addMessageStyle}>
            <AddMessage />
          </section>
        </section>
      </div>
    );
  }
} 

actions.js :存储addMessageToList操作。添加新消息后,我使用socket.emit

将其发送到服务器
export var addMessageToList = messageText => {
  let messageDtls = {};
  messageDtls.messageText = messageText;
  messageDtls.messageAuthor = "You";  //just for testing
  messageDtls.messageID = "You" + messageText;  //just for testing
  socket.emit("addmessage", messageDtls);

  return {
    type: actionTypes.ADD_MESSAGE_TO_LIST,
    payLoad: { messageDtls: messageDtls }
  };
};

reducer.js -减速器包含messagesList作为状态值,其中包含来自所有用户(包括当前)的所有消息。

var initState = {
  messagesList: []
};

var addMessageToList = (state, action) => {
  return {
    ...state,
    messagesList: [...state.messagesList, action.payLoad.messageDtls]
  };
};

var reducer = (state = initState, action) => {
  switch (action.type) {
    case actionTypes.ADD_MESSAGE_TO_LIST:
      return addMessageToList(state, action);
    default:
      return state;
  }
};
export default reducer;

Messages.js -该组件使用map作为列表来呈现每个Message组件。 messagesList来自redux存储。

class Messages extends Component {
  render() {
    let messages = null;
    messages =
      this.props.messagesList &&
      this.props.messagesList.map((ele, index) => {
        return (
          <Message
            key={index}
            messageAuthor={ele.messageAuthor}
            messageText={ele.messageText}
          />
        );
      });

    const { classes } = this.props;
    return (
      <Card className={classes.card} raised={true}>
        <span>Messages</span>
        <CardContent className={classes.cardContent}>{messages}</CardContent>
      </Card>
    );
  }
}

var mapStateToProps = state => {
  return {
    messagesList: state.messagesList
  };
};

var mapDispatchToProps = dispatch => {
  return {
    addMessageToList: messageText =>
      dispatch(actions.addMessageToList(messageText))
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(withStyles(styles)(Messages));

AddMessage.js -在单击按钮时分派action addMessageToList的组件,以便可以在messagesList状态下添加消息。

class AddMessage extends Component {
  state = {
    value: ""
  };
  handleChange = event => {
    this.setState({
      value: event.target.value
    });
  };

  onEnterKeyPress = event => {
    this.props.addMessageToList(this.state.value);
    this.setState({
      value: ""
    });
  };
  render() {
    const { classes } = this.props;
    return (
      <Paper className={classes.root} elevation={1}>
        <InputBase
          className={classes.input}
          placeholder="Message"
          onChange={this.handleChange}
          value={this.state.value}
          // onKeyPress={this.onEnterKeyPress}
        />
        <IconButton
          className={classes.iconButton}
          aria-label="Enter"
          onClick={this.onEnterKeyPress}
          disabled={this.state.value === "" ? true : false}
        >
          <ChatIcon />
        </IconButton>
      </Paper>
    );
  }
}

var mapDispatchToProps = dispatch => {
  return {
    addMessageToList: messageText =>
      dispatch(actions.addMessageToList(messageText))
  };
};

export default connect(
  null,
  mapDispatchToProps
)(withStyles(styles)(AddMessage));

后端App.js -从App.js文件中提取的内容,在与套接字连接时,我收听“ addmessage”事件并广播发出“ messagesadded”事件。

io.on("connection", socket => {
  console.log("User connected");
  socket.on("addmessage", message => {
    // messagesRecieved = message.messageText;
    console.log("Message received : " + message.messageText);
    socket.broadcast.emit("messagesadded", message);
  });
});

现在我不确定我应该在我的React代码中的哪个地方监听从服务器广播的'messagesadded'事件。它应该像连续监听一样,以便每当传输一条消息时,我都可以再次调度addMessageToList操作,它将更新messagesList状态并再次呈现Messages组件。

谢谢。

1 个答案:

答案 0 :(得分:0)

您应该在componentDidMount()中监听套接字事件。

componentDidMount(){
 socket.on("messagesadded", message => {
  //dispatch action
});
}