简体   繁体   English

Reactjs:如何在组件之间共享 websocket

[英]Reactjs: how to share a websocket between components

I'm new to React and I'm having some issues regarding components structure and sharing a websocket between them.我是 React 新手,我在组件结构和在它们之间共享 websocket 方面遇到了一些问题。

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.初始数据加载将通过 Ajax 请求完成,websocket 将用于保持数据更新。

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. CategoriesList 保存类别的 state,ProductsList 保存类别中产品的 state。

So I would like to use the same websocket inside CategoriesList and ProductsList but listening to different websocket events: category:updated and product:updated.所以我想在 CategoriesList 和 ProductsList 中使用相同的 websocket 但监听不同的 websocket 事件:类别:更新和产品:更新。

How do I share the websocket between components and where is the right place to initialize it?如何在组件之间共享 websocket 以及初始化它的正确位置在哪里?

Since there is one ProductsList for each Category, does this means that the products:updated event will fire multiple times ( one for each category )?由于每个类别都有一个 ProductsList,这是否意味着 products:updated 事件将触发多次(每个类别一个)? I guess this isn't a good thing in terms of performance.我想这在性能方面不是一件好事。

Another way of sharing the same instance is simply create a new file as below: socketConfig.js共享同一个实例的另一种方法是简单地创建一个新文件,如下所示: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.这对我有用,因为我在 2 个不相互依赖的不同组件中使用它。

I recommend initializing your socket connection in CategoriesList and then passing down the connection as props to the child components.我建议在 CategoriesList 中初始化您的套接字连接,然后将连接作为道具传递给子组件。 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.这是 github 上使用 react 和 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 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.在第 9 行,连接被初始化,然后在第 23 行,它作为 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例如: https : //github.com/raineroviir/react-redux-socketio-chat/blob/master/src/common/components/Chat.js

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>);
}

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.如果您使用 Redux Store,则将socket存储在 Redux Store 中,然后您可以像其他存储变量/状态一样从任何组件访问它。

Component: A (Defining Socket in Component A)组件:A (在组件A中定义Socket)

 //... 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)组件:B (在另一个组件中使用 Socket)

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

Create socket.config.js file add open connection for your websockets.创建 socket.config.js 文件,为您的 websocket 添加打开的连接。

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 挂钩使用 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.参见react-cent可以编写自己的 Provider (CentProvider.js) 来包装你的组件,并通过上下文提供你的客户端。 In addition, write Higher-Order Component (CentComponent.js) to make it available with this.props.<client>此外,编写高阶组件 (CentComponent.js) 使其与this.props.<client>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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