我正在使用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组件。
谢谢。
答案 0 :(得分:0)
您应该在componentDidMount()
中监听套接字事件。
componentDidMount(){
socket.on("messagesadded", message => {
//dispatch action
});
}