Везде в примерах c socket.io используются jquery, ajax'ы всякие. И найти хороший пример приёма сообщений на реакте мне не удалось.
Проверил свой server.js с помощью сайта socketserve.io:
Как видно, сообщение удачно отправлено.
Код
server.js:
const app = require('express')()
const http = require('http').Server(app)
const io = require('socket.io')(http)
const port = 8000
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/index.html')
})
io.on('connection', client => {
let addedUser = false
// При подключении с помощью componentDidMount делаю emit эвента 'new user'
client.on('new user', username => {
if (addedUser) return
client.username = username
addedUser = true
console.log(`${client.username} joined`)
client.broadcast.emit('user join', { username: client.username })
})
// Отправка сообщений
client.on('new message', data => {
console.log('MSG: ', data)
io.emit('new message', { message: data })
})
client.on('disconnect', () => {
console.log(`${client.username} has disconnected`)
})
})
http.listen(port, () => {
console.log(`listening on *:${port}`)
})
Компонент:
import React, { Component } from 'react'
import { createGlobalStyle } from 'styled-components'
import openSocket from 'socket.io-client'
// import SocketIOClient from 'socket.io-client'
// const socket = SocketIOClient('http://localhost:8000/')
const socket = openSocket('http://localhost:8000/')
const name = 'Jeff'
const GlobalStyle = createGlobalStyle`
body {
background-color: #1e1f26;
color: #DBDBD4;
}
* {
font-family: 'Roboto Condensed', sans-serif;
}
`
class App extends Component {
constructor(props) {
super(props)
this.state = {
text: '',
messages: []
}
}
componentDidMount = () => {
socket.emit('new user', name)
}
handleChange = e => {
this.setState(state => ({ ...state, text: e.target.value }))
}
handleSubmit = e => {
e.preventDefault()
console.log('submited')
this.setState(state => ({ ...state, text: '' }))
socket.emit('new message', this.state.text)
}
render() {
return (
<div>
<GlobalStyle />
<form onSubmit={this.handleSubmit}>
<input onChange={this.handleChange} value={this.state.text} />
</form>
<div>
{this.state.messages.map((message, index) => (
<p key={index}>{message}</p>
))}
</div>
</div>
)
}
}
export default App
Код для приёма сообщений:
socket.on('new message', data => {
this.setState(state => ({
...state,
text: '',
messages: [...state.messages, data.message]
}))
})
Куда всунуть этот код? в
render() ?
Вставил в рендер:
(Пробовал вставлять в
handleSubmit, и в
componentDidUpdate. Один фиг либо не работает, либо криво, как на последнем скрине)
И работает оно невероятно криво:
(Как видно, отправил я всего лишь 2 сообщения, но отправилось гораздо больше)
Как пользоваться Socket.io вместе с реактом? Как получить новое сообщение от другого клиента, чтобы оно не отрисовывалось миллион сто раз?