reactjs - 如何存储 socket-io-client 实例以通过应用程序访问

标签 reactjs websocket socket.io react-hooks

我正在使用react hook来创建应用程序,并使用socket.io-client用于flask和react之间的通信,尝试访问应用程序的不同组件中的socket.io-client实例,

请检查socket-Instance.js内的以下代码,连接后创建了socketio实例并使用dispatch存储在store.js中,

在 device.js 中,尝试访问存储的套接字实例,并在切换时发出数据,

但是在套接字实例中,我试图打印 console.log(socketInstance); 这是 null

我想创建一次套接字实例,并尝试使用连接的套接字从不同的组件发出数据

使用 https://www.npmjs.com/package/socket.io-client这个库

索引.js

import { StateProvider } from './shared/store';
const app = (
    <StateProvider>
        <AppRouting />
        <SocketInstance />
    </StateProvider>
);

store.js

import React, { createContext, useReducer } from 'react';

const initialState = {
    deviceStatus: []
};
const store = createContext(initialState);
const { Provider } = store;

const StateProvider = ({ children }) => {
    const [state, dispatch] = useReducer((currentState, action) => {
        const newState = { ...currentState };
        console.log(action.type);
     switch (action.type) {
      case 'socket':
                newState.websocket = action.currentState
                return newState

            default:
                throw new Error();
        };
    }, initialState);

    return <Provider value={{ state, dispatch }}>{children}</Provider>;
};

export { store, StateProvider }

socket-instance.js

mport React, { useEffect, useContext, useState } from 'react';
import { store } from '../shared/store';
import socketio from 'socket.io-client';
const ENDPOINT = "http://localhost:5000/";

function SocketInstance() {
    const { dispatch } = useContext(store);
    const [socketInstance, setSocket] = useState(null);

    useEffect(() => {

        const currentSocket = socketio.connect(ENDPOINT, {
            reconnection: true
        })

        currentSocket.on('connect', function (msg) {
            console.log("Server connected...");
        });

        currentSocket.on("disconnect", function () {
            console.log("server disconnected from client");
        });
        setSocket(currentSocket)

        console.log("=======set socket instance==========");

        console.log(socketInstance);


        dispatch({ type: 'socket', socket: socketInstance })


    }, [])

    return (
        <div >

        </div>
    )

}

export default SocketInstance;

device.js


function DeviceStatus() {

    const { state, dispatch } = useContext(store);
    const { deviceStatus, websocket } = state; //deviceCommand should be same as setting new state in store
    const [isEnable, setIsEnabled] = useState(false)
    const toggleSwitch = (checked) => {
        setIsEnabled(checked)
        dispatch({
            type: "updateDeviceStatus",
            deviceId: 21,
            deviceState: checked,
        })

        console.log("******before emit***************");
        console.log(deviceStatus);
        console.log("******check websocket ***************");
        console.log(websocket);
        if (websocket) {
            console.log("websocket instance can accessible");

            // websocket.emit("datafromui", deviceStatusFromUI)
        }
    }
return (
      <div className="devicestatus-item" >
                        <span>{DeviceStatusConst.FRONT_LL}</span>
                        <Switch checked={isEnable} onChange={toggleSwitch} />
                    </div>


  )
}
export default DeviceStatus

非常感谢您的帮助,“提前致谢

最佳答案

SocketInstance 的 useEffect 有一个空的依赖数组,这意味着它只会在第一次渲染后运行一次。它记录 null,因为状态在下一次渲染之前不会更新。

就跨组件使用相同的实例而言,您可以简单地在组件外部定义 currentSocket(或在单独的文件中并将其导出)并将其作为 props 向下传递。更好的是,您可以使用上下文来代替。另外,我建议在 SocketInstance 组件卸载时清理事件监听器。

CreateContext.js

import React from 'react'
import socketio from 'socket.io-client'

export const socket = socketio('http://localhost:5000/')
const SocketContext = React.createContext(socket)

export const SocketProvider = SocketContext.Provider
export const SocketConsumer = SocketContext.Consumer
export default SocketContext

Index.js

import { StateProvider } from './shared/store'
import { SocketProvider } from './shared/context/SocketContext'

const app = (
    <StateProvider>
      <SocketProvider>
        <AppRouting />
          <SocketInstance />
      </SocketProvider>
    </StateProvider>
)

socket-instance.js

import React from 'react'
import SocketContext from './shared/context/SocketContext'

const SocketInstance = () => {
  const currentSocket = React.useContext(SocketContext)

  React.useEffect(() => {
    console.log(currentSocket)

    const listener = message => {
      console.log(message)
    }

    currentSocket.on('some-event', listener)

    return () => currentSocket.off('some-event', listener)
  }, [])

  return (
    <div></div>
  )
}

关于reactjs - 如何存储 socket-io-client 实例以通过应用程序访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64482843/

相关文章:

javascript - 使用 Froala 编辑器配置 React JS ES6

java - 使用 Spring Rabbitmq Stomp 的持久队列

javascript - Socket.IO ( nodejs ) 中的 Windows Phone 支持

javascript - 我怎样才能使用socket.io(而不是每个人)向单个客户端发出信号

javascript - 后缺少名称。用于 socket.io js 文件的运算符(operator) YUI 压缩器

javascript - 尝试使用 map 映射一系列 url 图像以渲染到卡片

reactjs - 传递函数调用来处理嵌套状态更改。我在这里做错了什么?

javascript - ReactJs:如何获取引用来自其父项的组件的引用

php - WebSocket 握手期间出错 : Unexpected response code: 200

node.js - 反向代理 websockets (SSL),通过 Stunnel 到许多 node.js 应用程序的流量