'ReactJS, SocketIO & Redux - What is the right design

What is the best pattern for a large multi-component ReactJS app to integrate with a socket io back-end server?

Here are some of the requirements

  1. The React application must connect to the backend (a server using a Flask-based socket.io implementation) upon login. The connection must be torn down on logout
  2. The connection should be managed from a central place (as in I don't want every component to connect/disconnect to socket-io). This should also be a place to manage life-cycle of the socketio connection (disconnect, reconnect, etc).
  3. Back-end will send async updates (a.k.a statistics for various components). These stats must be handled by the common socketio handling instance and pushed into redux store. The message body will have enough information to demux the messages.
  4. The components themselves, should (preferably) not know about socket-io, they operate on the redux state.
  5. Components can dispatch actions, that could potentially result in sending out a socketio message (to back-end).
  6. [I don't have a use-case where a client needs to talk to another client.]

Few questions:

  1. What is the right way to design this? At what point should I connect to socket-io?
  2. I have a basic-layout component which is used by all pages. Is this the right place to hook up socket-io call? However, I see that this component is unloaded/loaded for each page. Somehow, this doesn't feel like the right place
  3. I have seen some examples where every page opens a socketio connection. I am not sure if this is the right model?


Solution 1:[1]

I think you should probably store your socket on a Context, so that you can create your socket on your index.js file, like I did here :

import React from "react";
import App from "./App";
import socketIOClient from "socket.io-client";
import { MainProvider } from "./context/MainContext.js";

const ENDPOINT = "http://127.0.0.1:1234"; //Your backend endpoint

ReactDOM.render( 
  <React.StrictMode>
    <MainProvider value={{socket: socketIOClient(ENDPOINT)}}>
      <App />
    </MainProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

Then as it is on the context, you can access it in any component, like that :

import React, { useContext } from 'react';
import PropTypes from 'prop-types';

import MainContext from "./context/MainContext"; //import your context here

const myComponent = props => {

    const myContext = useContext(MainContext); //your context is stored in a prop

    return (
        <div></div>
    );
};

myComponent.propTypes = {
    
};

export default myComponent;

Finally you can access your socket in the component by calling myContext.socket

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Baptiste Rieber