admin管理员组

文章数量:1168549

I'm new to React and I'm having some issues regarding components structure and sharing a websocket between them.

The app consists of categories and products. The initial data load will be done with an Ajax request and a websocket will be used keep data updated.

My component hierarchy looks like this:

  • CategoriesList
    • Category
      • ProductsList
        • Product

CategoriesList holds the state of categories and ProductsList holds the state of products within a category.

So I would like to use the same websocket inside CategoriesList and ProductsList but listening to different websocket events: category:updated and product:updated.

How do I share the websocket between components and where is the right place to initialize it?

Since there is one ProductsList for each Category, does this means that the products:updated event will fire multiple times ( one for each category )? I guess this isn't a good thing in terms of performance.

I'm new to React and I'm having some issues regarding components structure and sharing a websocket between them.

The app consists of categories and products. The initial data load will be done with an Ajax request and a websocket will be used keep data updated.

My component hierarchy looks like this:

  • CategoriesList
    • Category
      • ProductsList
        • Product

CategoriesList holds the state of categories and ProductsList holds the state of products within a category.

So I would like to use the same websocket inside CategoriesList and ProductsList but listening to different websocket events: category:updated and product:updated.

How do I share the websocket between components and where is the right place to initialize it?

Since there is one ProductsList for each Category, does this means that the products:updated event will fire multiple times ( one for each category )? I guess this isn't a good thing in terms of performance.

Share Improve this question asked Mar 20, 2016 at 21:57 FernandoFernando 4,6194 gold badges28 silver badges40 bronze badges 3
  • I will use tweet to describe how much React cares about your implementation twitter.com/AdamRackis/status/707004963776430080 I would pass down socket connection instance (via context maybe?!) which will allow components to listen to changes. Feel free to use whatever you are comfortable with. React will not limit you. – Andreyco Commented Mar 20, 2016 at 22:19
  • Yes, you share it by passing it through props, or use an architecture like Flux where the socket lives in a store you can access from anywhere. Listen to events in componentDidMount and unlisten for events in componentWillUnmount. Are you using any web-socket library, for example Socket.IO? – Aaron Beall Commented Mar 21, 2016 at 0:06
  • @Aaron I'm using the library provided by Pusher.com – Fernando Commented Mar 22, 2016 at 14:31
Add a comment  | 

6 Answers 6

Reset to default 22

Another way of sharing the same instance is simply create a new file as below: socketConfig.js

import openSocket from 'socket.io-client';

const socket = openSocket("http://localhost:6600");

export default socket;

and the use it in any file you want, just import it.

import socket from "../socketConfig";

This works for me, as I use it in 2 different components which are not depend on each other.

I recommend initializing your socket connection in CategoriesList and then passing down the connection as props to the child components. When the connection is passed down, you should be able to use it to listen for specific events as needed in the child components.

Here's an example application on github that uses react and socket.io. The socket is initialized in a parent component and then passed down. https://github.com/raineroviir/react-redux-socketio-chat/blob/master/src/common/containers/ChatContainer.js

On line 9 the connection is initialized and then on line 23 it's passed down as props. The connection is later used in child components to receive and emit events. Ex: https://github.com/raineroviir/react-redux-socketio-chat/blob/master/src/common/components/Chat.js

If you are using Redux Store, then store the socket in Redux Store and then you can access it from any component as like other store variable/state.

Component: A (Defining Socket in Component A)

//...
const dispatch = useDispatch();

useEffect(() => {
  const socket = io("http://localhost:8000");
  socket.on("connect", () => {
    console.log("Connected to Socket");
    dispatch({
      type: "INIT_SOCKET",
      socket: socket
    });
  });
}, [...]);

Component: B (Using Socket in another Component)

//...
const socket = useSelector(state => state.socket);

useEffect(() => {
  if (socket) {
    socket.on("msg", (data) => {
      console.log(data);
    });
  }
}, [socket]);

Just declare socket outside component, same this...

import SocketIOClient from 'socket.io-client';   
const socket=SocketIOClient('http://localhost:3000/chat')

function App() {
    //use socket here ...

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

Create socket.config.js file add open connection for your websockets.

export const WebSocket1 = new WebSocket('ws://YOUR websocketurl');
export const WebSocket2 = new WebSocket('ws://YOUR anotherwebsocketurl');

Import into your any component

import  {WebSocket1, WebSocket2}from '../../../utils/socket.config';

Inside UseEffect hooks utilise the websocket

 useEffect(() => {
WebSocket1.onopen = () => {
    WebSocket1.send(JSON.stringify(someData));
};

    WebSocket1.onmessage = (event: any) => {

      console.log(JSON.parse(event.data));
        
        
    }

    WebSocket1.onerror = error => {
        console.log(`WebSocket error: ${error}`);
    };

    WebSocket1.onclose = () => {
        console.log("disconnected");
    }
}, []);

See react-cent You can write your own Provider (CentProvider.js) to wrap your components and provide your client through the context. In addition, write Higher-Order Component (CentComponent.js) to make it available with this.props.<client>

本文标签: javascriptReactjs how to share a websocket between componentsStack Overflow