Created
May 15, 2019 14:21
-
-
Save ls-joris-desmedt/34168fd4e05ab40680c5078399750f15 to your computer and use it in GitHub Desktop.
Websockets + React Context
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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