cosmichero2025
cosmichero2025

Reputation: 1029

Poor performance with socket.io app

I'm attempting to have a socket.io app where the user selects a color and that makes the background-color of an element for ALL users that color. I have it working but after 15 clicks it starts to lag and it takes longer and longer for the server to respond with the data.

Could this be because of my implementation of it with react? I wasn't sure of the proper way to set it up with component life cycles.

Visualization

enter image description here

Client

import React, { Component } from 'react';
import io from 'socket.io-client';
import { SketchPicker } from 'react-color';

class App extends Component {
    constructor() {
        super();
        this.state = {
            background: '#ffffff'
        };

        this.socket = io.connect('http://localhost:5000');
    }

    handleChange = color => {
        this.socket.emit('colorChange', color.hex);
    };

    render() {
        const { background } = this.state;

        this.socket.on('changedColor', data => {
            this.setState({ background: data.color });
        });

        return (
            <div className="app" style={{ backgroundColor: background }}>
                <h1>Choose a color!</h1>
                <SketchPicker onChangeComplete={this.handleChange} color={background} />
            </div>
        );
    }
}

export default App;

(backend) SERVER

const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
// Port enviroment
const PORT = process.env.PORT || 5000;

app.use(express.static(__dirname + '/node_modules'));

app.get('/', (req, res, next) => {
  res.sendFile(__dirname + '/client/public');
});

server.listen(PORT, () => console.log(`Hey the server is online at port: ${PORT}`))

io.on('connection', (socket) => {
  console.log(`Socket connection: ${socket.id}`);

  socket.on('colorChange', (color) => {
    console.log(`The color: ${color} was sent from: ${socket.id}`);
    const colorMeta = {
      user: socket.id,
      color: color
    }
    io.sockets.emit('changedColor', colorMeta);
  });

  socket.on('disconnect', () => {
    console.log('Hey the IO server disconnected!');
  });

});

Upvotes: 0

Views: 1344

Answers (1)

Chris Foster
Chris Foster

Reputation: 2649

Don't bind the event listener in the render call. React is set up to be able to call render whenever it needs to, so it can compare the rendered component output with the previously existing DOM. Every time it calls a render, you're creating another event listener to your socket.

Since your socket has a long lifespan, you're going to collect a lot of event listeners onto it. Each one of those event listeners is going to call setState, which is likely going to lead to a rerender and even more event listeners being attached.

You'll want to bind that event listener in your constructor or in componentDidMount.

Upvotes: 1

Related Questions