-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.tsx
69 lines (57 loc) · 1.67 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import * as React from 'react'
interface PubSubProviderProps {
context?: PubSubContext
}
export type Handler = (message: unknown) => void
export function createPubSubContext(): PubSubContext {
const channels: {
[name: string]: Handler[]
} = {}
function publish(channel: string, message: unknown) {
const handlers = channels[channel] || []
for (const handler of handlers) {
handler(message)
}
}
function subscribe(channel: string, handler: Handler) {
const handlers = channels[channel] ? [...channels[channel]] : []
handlers.push(handler)
channels[channel] = handlers
return () => unsubscribe(channel, handler)
}
function unsubscribe(channel: string, handler: Handler) {
const handlers = channels[channel] || []
const i = handlers.indexOf(handler)
if (i !== -1) {
const newHandlers = [...handlers]
newHandlers.splice(i, 1)
channels[channel] = newHandlers
}
}
return {
publish,
subscribe,
unsubscribe,
}
}
export interface PubSubContext {
publish: (channel: string, message: unknown) => void
subscribe: (channel: string, handler: Handler) => () => void
unsubscribe: (channel: string, handler: Handler) => void
}
const ReactPubSubContext = React.createContext<PubSubContext | null>(null)
export const PubSubProvider: React.FC<PubSubProviderProps> = function(props) {
const { children, context } = props
return (
<ReactPubSubContext.Provider value={context || createPubSubContext()}>
{children}
</ReactPubSubContext.Provider>
)
}
export const usePubSub = (): PubSubContext => {
const context = React.useContext(ReactPubSubContext)
if (!context) {
throw new Error('usePubSub called outside of PubSubProvider')
}
return context
}