Я кодирую приложение чата, используя ReactJS, Socket.io, and NodeJS. Я завершил базовую часть подключения к сокету, и когда я ввожу сообщение и нажимаю ввод, сообщение отправляется на серверную часть. Теперь я хочу, чтобы после того, как кто-либо добавил сообщение (несколько вкладок), сообщение транслировалось всем остальным клиентам, кроме того, кто его инициировал, и должно отображаться в списке сообщений. Я передаю сообщение всем клиентам с сервера, когда сообщение получено от определенного клиента, но не знаю, где его поймать на моем интерфейсе в приложении реагирования.
Позвольте мне пройтись по коду:
App.js — Мое приложение состоит из 3 основных компонентов: Пользователи (список пользователей), Сообщения (список сообщений, в котором будут отображаться все сообщения для всех онлайн-пользователей) и 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>
);
}
}
действия.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 }
};
};
редуктор.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;
Сообщения.js — компонент отображает каждый компонент сообщения, используя карту в виде списка. Список сообщений поступает из хранилища избыточности.
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 — компонент, в котором действие addMessageToList отправляется при нажатии кнопки, чтобы сообщение можно было добавить в состояние messagesList.
class AddMessage extends Component {
state = {
value: ""
};
handleChangeEvent = 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.handleChangeEvent}
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.info("User connected");
socket.on("addmessage", message => {
// messagesRecieved = message.messageText;
console.info("Message received : " + message.messageText);
socket.broadcast.emit("messagesadded", message);
});
});
Теперь я не уверен, где в моем коде React я должен слушать событие «messagesadded», транслируемое с сервера. Это должно быть похоже на непрерывное прослушивание, чтобы всякий раз, когда сообщение передается, я мог снова отправить действие addMessageToList, и оно обновило состояние messagesList и снова отобразило компонент Messages.
Спасибо.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы должны прослушивать событие сокета в componentDidMount().
componentDidMount(){
socket.on("messagesadded", message => {
//dispatch action
});
}
@ShantanuTomar в вашем файле Сообщения.js. Вы можете реорганизовать свой код, преобразовав некоторые компоненты в компоненты без сохранения состояния. и сохраните Сообщения.js как компонент с полным состоянием. Вы можете проверить ввод (в компоненте добавления сообщения). Отправляйте сообщение отправки только тогда, когда вы нажимаете кнопку ввода при нажатии кнопки отправки, тогда это не будет проблемой.
Прошу прощения, но мне непонятно. Сообщения по-прежнему являются компонентом с отслеживанием состояния. И я не уверен, как здесь проявляется компонент AddMessage. Пожалуйста, если вы можете уточнить это, был бы признателен.
Спасибо за ответ. componentDidMount() какого компонента? Я пробовал это уже в сообщениях, но это какая-то бесконечная отправка. Более того, меня беспокоит то, что если я прослушаю его в любом из компонентов компонента componentDidMount(), для этого для вызова компонент должен быть смонтирован более чем n над. Что, если пользователь вводит сообщение, а затем сидит без дела и в другом окне, пользователь вводит и сообщение передается с сервера, componentDidMount() не сработает автоматически.