Skip to content

Instantly share code, notes, and snippets.

@blixt
Last active April 6, 2019 16:50
Show Gist options
  • Save blixt/64b77f58838ffaf56e8783e3ad0fa8c6 to your computer and use it in GitHub Desktop.
Save blixt/64b77f58838ffaf56e8783e3ad0fa8c6 to your computer and use it in GitHub Desktop.
import { useEffect, useRef, useState } from "react"
interface IO<T> {
setters: ((value: T) => void)[]
update: (value: T) => void
value: T | undefined
}
const store: { [name: string]: IO<any> | undefined } = {}
function getIO<T>(name: string): IO<T> {
if (store[name]) return store[name]
const io: IO<T> = {
setters: [],
update: (value: T) => {
io.value = value
io.setters.forEach(set => set(value))
},
value: undefined,
}
store[name] = io
return io
}
export function useInput<T = any>(name: string): T | undefined {
const io = getIO<T>(name)
const [value, setValue] = useState(io.value)
useEffect(() => {
io.setters.push(setValue)
return () => {
for (let i = io.setters.length - 1; i >= 0; i--) {
if (io.setters[i] === setValue) {
io.setters.splice(i, 1)
break
}
}
}
}, [])
return value
}
export function useOutput<T = any>(name: string): (value: T) => void {
return getIO<T>(name).update
}
export function useIO<T = any>(
name: string
): [T | undefined, (value: T) => void] {
return [useInput<T>(name), useOutput<T>(name)]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment