Задать вопрос
640
@640
Beginner

Как принимать сообщения в React компоненте используя socket.io?

Везде в примерах c socket.io используются jquery, ajax'ы всякие. И найти хороший пример приёма сообщений на реакте мне не удалось.
Проверил свой server.js с помощью сайта socketserve.io:
5c89673446816328879776.png

Как видно, сообщение удачно отправлено.
Код 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. Один фиг либо не работает, либо криво, как на последнем скрине)
5c896ae153dfb591443336.png

И работает оно невероятно криво:
(Как видно, отправил я всего лишь 2 сообщения, но отправилось гораздо больше)
5c896af87e0d1264994427.png
Как пользоваться Socket.io вместе с реактом? Как получить новое сообщение от другого клиента, чтобы оно не отрисовывалось миллион сто раз?
  • Вопрос задан
  • 3583 просмотра
Подписаться 1 Сложный Комментировать
Решения вопроса 3
0xD34F
@0xD34F Куратор тега React
Куда всунуть этот код? в render() ?

В componentDidMount.
Ответ написан
https://redux-saga.js.org/docs/introduction/Beginn...
С сокетами еще работает Apollo GraphQL

Рано или поздно всеравно прийдете или к первому или ко второму
Если хочется совсем просто https://reactjs.org/docs/react-component.html#the-...
Когда монтируете компонент - подписываетесь на сообщения, с каждым сообщением обновляете стейт компонента, когда демонтируете компонент не забудьте отписаться
Ответ написан
Комментировать
hzzzzl
@hzzzzl
так в componentDidMount(), не?
чтобы он при маунте начал слушать сообщение

я делал так, но не с socket.io а с https://developer.mozilla.org/en-US/docs/Web/API/E... , то есть "односторонним" сокетом сервер->клиент

this.eventSource = new EventSource("http://localhost:5000/api/......")

  componentDidMount() {
    ......
    this.subscribeToServerEvent()
  }

  subscribeToServerEvent = () => {
    this.eventSource.onmessage = e => {
      try {
        ......
        this.setState({ ..... })
      } catch (e) {
        console.log('error parsing server response', e)
      }
    }
  }
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы