简体   繁体   中英

ReactJS + Socket.IO - Best way to handle socket connection

I'm trying to make a ReactJS realtime application with Node and Socket.IO, but I'm having a hard time figuring out the best way to handle my socket connection on the clientside.

I have multiple React components that all need some information from the server, and preferrably in realtime via the socket connection. But when importing the socket.io-client dependency and making the connection to the server in different files, I get multiple connections to the server, which doesn't really seem that optimal.

So I'm wondering if there's a better solution to share the connection between multiple components without having to create a new connection for each component. Maybe by making connection in the main app.js file and then passing it onto the child components for later use.

Some places online suggests using the context property to pass the socket variable, but React's own documentation highly discourage the use of context .

The following code is just an example, not the actual code since there's much more unnecessary code in the real project than needed to illustrate the problem.

foo.js

import React from 'react';
import io from 'socket.io-client';

const socket = io("http://localhost:3000");

class Foo extends React.Component {
    // ...
    componentDidMount() {
        socket.on("GetFooData", (data) => {
            this.setState({
                fooData: data
            });
        });
    }
    // ...
}

bar.js

import React from 'react';
import io from 'socket.io-client';

const socket = io("http://localhost:3000");

class Bar extends React.Component {
    // ...
    componentDidMount() {
        socket.on("GetBarData", (data) => {
            this.setState({
                barData: data
            });
        });
    }
    // ...
}

app.js

import React from 'react';
import ReactDOM from 'react-dom';
import Foo from './foo';
import Bar from './bar';

const App = () => {
    return (
        <div className="container">
            <Foo />
            <Bar />
        </div>
    );
};

ReactDOM.render(
    <App />,
    document.getElementById("root")
);

Old question, but let me answer this for the googlers.

I was also considering the context, but instead went for passing it as a props, but a problem happened where I couldn't actually pass it the way I wanted due to react-route. Either the route props (such as history to redirect) didn't work or the socket connection didn't get passed.

So the solution is actually passing the socket variable as a props, but with having a bit of a different structure. In case you are using a route it adds another thing. You actually need to render the component in a kinda different way.

So for me, this code

<Route path="/game" component={Game} />} />

changes to

<Route path="/game" render={(props) => <Game {...props} socket={this.state.socket} />} />

As for connecting the socket I do it inside the componentWillMount like so.

  constructor(props) {
    super(props);
    this.state = {
      socket: false,
    }
  }
  componentWillMount() {
    let socket = io("http://localhost:5000");
    this.setState({socket});
  }

Edit: Well apparently this isn't really the best way, when passing the socket connection some stuff simply don't work such as same session between socket and express.

You can create one socket connection and then export it ,like this,

import io from "socket.io-client";
let socket = io("http://localhost:8000/chat");
export default socket;

and then import it anywhere

import socket from "../../socket/socket";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM