Skip to content

Instantly share code, notes, and snippets.

@ls-joris-desmedt
Created May 15, 2019 14:21
Show Gist options
  • Save ls-joris-desmedt/34168fd4e05ab40680c5078399750f15 to your computer and use it in GitHub Desktop.
Save ls-joris-desmedt/34168fd4e05ab40680c5078399750f15 to your computer and use it in GitHub Desktop.
Websockets + React Context
import React, { ReactNode, useContext, useEffect, useState } from 'react';
import { Websocket } from './websocket';
export type EchoWebSocketContextType = [
(event: any, filter?: string) => void,
(event: any) => void
];
export const EchoWebSocketContext = React.createContext<EchoWebSocketContextType>([
() => {},
() => {},
]);
export const EchoWebSocketProvider = ({ children }: { children: ReactNode }) => {
const [webSocket, setWebSocket] = useState<WebSocket | null>(null);
const [listeners, setListeners] = useState<{
[key: string]: ((event: any) => void)[];
}>({});
const addListener = (fn: any, filter = 'any') => {
setListeners(currentListeners => {
console.log(currentListeners);
return { ...currentListeners, [filter]: [...(currentListeners[filter] || []), fn] };
});
};
const sendMessage = (message: string) => {
if (webSocket) {
webSocket.send(message);
}
};
const onMessage = (event: any) => {
const { data } = event;
if (listeners[data]) {
listeners[data].forEach(listener => listener(event));
}
if (listeners.any) {
listeners.any.forEach(listener => listener(event));
}
};
return (
<EchoWebSocketContext.Provider value={[addListener, sendMessage]}>
<Websocket
url="wss://echo.websocket.org"
onOpen={(_event, socket) => {
setWebSocket(socket);
console.log('Connected to websocket');
}}
onMessage={onMessage}
/>
{children}
</EchoWebSocketContext.Provider>
);
};
export const useEchoWebSocket = (listener?: (event: any) => void, filter = 'any') => {
const [addListener, sendMessage] = useContext(EchoWebSocketContext);
useEffect(() => {
if (listener) {
addListener(listener, filter);
}
}, []);
return { sendMessage };
};
import React, { ReactNode, useContext, useEffect, useState } from 'react';
import { Websocket } from './websocket';
export type EchoWebSocketContextType = [
(event: any, filter?: string) => void,
(event: any) => void
];
export const EchoWebSocketContext = React.createContext<EchoWebSocketContextType>([
() => {},
() => {},
]);
export const EchoWebSocketProvider = ({ children }: { children: ReactNode }) => {
const [webSocket, setWebSocket] = useState<WebSocket | null>(null);
const [listeners, setListeners] = useState<{
[key: string]: ((event: any) => void)[];
}>({});
const addListener = (fn: any, filter = 'any') => {
setListeners(currentListeners => {
console.log(currentListeners);
return { ...currentListeners, [filter]: [...(currentListeners[filter] || []), fn] };
});
};
const sendMessage = (message: string) => {
if (webSocket) {
webSocket.send(message);
}
};
const onMessage = (event: any) => {
const { data } = event;
if (listeners[data]) {
listeners[data].forEach(listener => listener(event));
}
if (listeners.any) {
listeners.any.forEach(listener => listener(event));
}
};
return (
<EchoWebSocketContext.Provider value={[addListener, sendMessage]}>
<Websocket
url="wss://echo.websocket.org"
onOpen={(_event, socket) => {
setWebSocket(socket);
console.log('Connected to websocket');
}}
onMessage={onMessage}
/>
{children}
</EchoWebSocketContext.Provider>
);
};
export const useEchoWebSocket = (listener?: (event: any) => void, filter = 'any') => {
const [addListener, sendMessage] = useContext(EchoWebSocketContext);
useEffect(() => {
if (listener) {
addListener(listener, filter);
}
}, []);
return { sendMessage };
};
import React, { useEffect, useState } from 'react';
export interface WebsocketProps {
url: string;
onMessage: (event: MessageEvent, websocket: WebSocket) => void;
onOpen: (event: Event, websocket: WebSocket) => void;
keepAliveInterval?: number;
onClose?: (event: Event, websocket: WebSocket) => void;
}
const keepAlive = (websocket: WebSocket, interval: number) => {
setTimeout(() => {
websocket.send(
JSON.stringify({
method: 'ping',
}),
);
keepAlive(websocket, interval);
}, interval);
};
export const Websocket = ({
url,
onMessage,
onOpen,
keepAliveInterval,
onClose,
}: WebsocketProps) => {
const [websocket, setWebsocket] = useState<any>(null);
useEffect(() => {
const websocket = new WebSocket(url);
websocket.onmessage = (event: MessageEvent) => {
onMessage(event, websocket);
};
if (onClose) {
websocket.onclose = (event: Event) => {
onClose(event, websocket);
};
}
websocket.onopen = (event: Event) => {
setWebsocket(websocket);
onOpen(event, websocket);
if (keepAliveInterval) {
keepAlive(websocket, keepAliveInterval);
}
};
}, []);
useEffect(() => {
if (websocket) {
websocket.onmessage = (event: MessageEvent) => {
onMessage(event, websocket);
};
}
}, [onMessage]);
return null;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment