Markus Hayner
Markus Hayner

Reputation: 2959

Using Socket.IO in React globally?

I am really interested in finding a solution to use socket.io on client-side globally. For now, I am calling the function below in every page and component where I use the events which I don't think is the right way. I want to mention as well that I am using redux to store my user.

// Connect to Socket.IO
const socket = socketIOClient(process.env.REACT_APP_BASE_URL, {
  query: `type=client&id=${user_id}`,
});

Upvotes: 1

Views: 2038

Answers (1)

Markus Hayner
Markus Hayner

Reputation: 2959

So the way I've done it was to create a Socket context file like this

WebSocket.js

import React, { createContext } from "react";
import io from "socket.io-client";
// REDUX
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { addOrder } from "./redux/actions";

const WebSocketContext = createContext(null);

export { WebSocketContext };

const WebSocket = ({ children, actions, user }) => {
  let socket;
  let ws;

  // EMIT EVENTS
  const newOrder = (data) => {
    socket.emit("newOrder", data);
  };

  // ON EVENTS
  const newDriverAccepted = (callback) => {
    socket.on("newDriverAccepted", (driver) => {
      actions.addOrder(driver);
      callback(true);
    });
  };

  if (!socket) {
    socket = io.connect(process.env.REACT_APP_BASE_URL, {
      query: `type=client&id=${user.id}`,
    });

    ws = {
      socket: socket,
      newOrder,
      newDriverAccepted,
    };
  }

  return (
    <WebSocketContext.Provider value={ws}>{children}</WebSocketContext.Provider>
  );
};

const mapDispatchToProps = (dispatch) => {
  const actions = {
    addOrder,
  };
  return {
    actions: bindActionCreators(actions, dispatch),
  };
};

const mapStateToProps = (state) => {
  return {
    user: state.clients.user,
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(WebSocket);

Then I've used it like this

index.js

import WebSocketProvider from "./WebSocket";

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <WebSocketProvider>
        <App />
      </WebSocketProvider>
    </PersistGate>
  </Provider>,
  document.getElementById("root")
);

And in component like this

import React, { useContext } from "react";
import { WebSocketContext } from "../../WebSocket";

const MyComponent = () => {
    const socket = useContext(WebSocketContext);

    const handleNewOrder = () => {
         const data = {...}
         socket.newOrder(data);
    } 
    return (
     ...
  )
}

Upvotes: 1

Related Questions