Reputation: 1029
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
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
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