【问题标题】:Reactjs: how to share a websocket between componentsReactjs:如何在组件之间共享 websocket
【发布时间】:2016-07-07 07:36:55
【问题描述】:

我是 React 新手,在组件结构和在它们之间共享 websocket 方面遇到了一些问题。

该应用由类别和产品组成。初始数据加载将通过 Ajax 请求完成,并将使用 websocket 保持数据更新。

我的组件层次结构如下所示:

  • 类别列表
    • 类别
      • 产品列表
        • 产品

CategoriesList 保存类别的状态,ProductsList 保存类别中产品的状态。

所以我想在 CategoriesList 和 ProductsList 中使用相同的 websocket,但监听不同的 websocket 事件:category:updated 和 product:updated。

如何在组件之间共享 websocket 以及初始化它的正确位置在哪里?

由于每个类别都有一个 ProductsList,这是否意味着 products:updated 事件将触发多次(每个类别一次)?我想这在性能方面不是一件好事。

【问题讨论】:

  • 我将使用 tweet 来描述 React 对您的实现的关心程度twitter.com/AdamRackis/status/707004963776430080 我将传递套接字连接实例(可能是通过上下文?!)这将允许组件监听更改。随意使用任何你觉得舒服的东西。 React 不会限制你。
  • 是的,您可以通过 props 传递它来共享它,或者使用像 Flux 这样的架构,其中套接字位于可以从任何地方访问的商店中。监听componentDidMount 中的事件并取消监听componentWillUnmount 中的事件。您是否在使用任何 web-socket 库,例如 Socket.IO?
  • @Aaron 我正在使用 Pusher.com 提供的库

标签: javascript reactjs websocket


【解决方案1】:

如果您使用的是 Redux Store,则将 socket 存储在 Redux Store 中,然后您可以像其他存储变量/状态一样从任何组件访问它。

组件:A(在组件 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
    });
  });
}, [...]);

组件:B(在另一个组件中使用 Socket)

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

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

【讨论】:

    【解决方案2】:

    只需在组件外声明套接字,同样...

    import SocketIOClient from 'socket.io-client';   
    const socket=SocketIOClient('http://localhost:3000/chat')
    
    function App() {
        //use socket here ...
    
        return (
            <div> </div>);
    }
    

    【讨论】:

    【解决方案3】:

    共享同一个实例的另一种方法是简单地创建一个新文件,如下所示:socketConfig.js

    import openSocket from 'socket.io-client';
    
    const socket = openSocket("http://localhost:6600");
    
    export default socket;
    

    在任何你想要的文件中使用它,只需导入它。

    import socket from "../socketConfig";
    

    这对我有用,因为我在两个不相互依赖的不同组件中使用它。

    【讨论】:

    • 这是有帮助的答案!一个扩展:如果 URL 本身是动态的并且依赖于将值加载到其中的组件,你会怎么做? openSocket(dynamicUrlHere)
    • 您好,如果您能帮助我,我有一个非常相似的问题。 stackoverflow.com/questions/65277256/…
    • 如何在 react 和 JS 中使用它?即我有一个使用 react 的 Phaser 游戏的 JS 文件
    【解决方案4】:

    见react-cent 您可以编写自己的 Provider (CentProvider.js) 来包装您的组件并通过上下文提供您的客户端。另外,编写高阶组件(CentComponent.js)使其与this.props.&lt;client&gt;一起可用

    【讨论】:

    • 这个答案(对一个老问题)在很大程度上依赖于一个可能并不总是存在的第三方包的链接。将来,请通过在您的文本中包含特定于 OP 问题的信息来回答
    【解决方案5】:

    我建议在 CategoriesList 中初始化您的套接字连接,然后将连接作为道具传递给子组件。当连接向下传递时,您应该能够根据需要使用它来侦听子组件中的特定事件。

    这是 github 上使用 react 和 socket.io 的示例应用程序。套接字在父组件中初始化,然后向下传递。 https://github.com/raineroviir/react-redux-socketio-chat/blob/master/src/common/containers/ChatContainer.js

    在第 9 行初始化连接,然后在第 23 行将其作为道具传递。该连接稍后在子组件中用于接收和发出事件。例如:https://github.com/raineroviir/react-redux-socketio-chat/blob/master/src/common/components/Chat.js

    【讨论】:

    • Render 将在服务器端创建多个连接。这不是最佳选择。
    猜你喜欢
    • 2017-08-16
    • 2015-08-25
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 2020-08-31
    • 2016-04-20
    相关资源
    最近更新 更多