Skip to content

Instantly share code, notes, and snippets.

@souporserious
Last active July 25, 2022 19:56
Show Gist options
  • Save souporserious/3c812977ffbdff5e1d9956760daf18f7 to your computer and use it in GitHub Desktop.
Save souporserious/3c812977ffbdff5e1d9956760daf18f7 to your computer and use it in GitHub Desktop.
import * as React from 'react'
import { suspend } from 'suspend-react'
import { useIndexedChildren, useIndex } from 'use-indexed-children'
import mitt from 'mitt'
type EmitterContextValue = ReturnType<typeof mitt> | null
const EmitterContext = React.createContext<EmitterContextValue>(null)
type ChildrenMapContextValue = Map<string, any> | null
const ChildrenMapContext = React.createContext<ChildrenMapContextValue>(null)
const isServer = typeof window === 'undefined'
function Child({
children,
duration = 1,
}: {
children: React.ReactNode
duration?: number
}) {
const emitter = React.useContext(EmitterContext)!
const childrenMap = React.useContext(ChildrenMapContext)!
const index = useIndex()!
childrenMap.set(index.indexPathString, { duration })
const data = suspend(async () => {
return new Promise((resolve) => {
function handleReady() {
const childrenValues = Array.from(childrenMap.values())
resolve(childrenValues)
emitter.off('children-updated', handleReady)
}
emitter.on('children-updated', handleReady)
if (index.index === index.maxIndex - 1) {
emitter.emit('children-updated')
}
})
}, index.indexPath)
return (
<div>
{children} {JSON.stringify(data)}
</div>
)
}
function Children({ children }: { children: React.ReactNode }) {
const indexedChildren = useIndexedChildren(children)
return indexedChildren
}
export default function App() {
const emitter = React.useRef<EmitterContextValue>(null)
if (emitter.current === null) {
emitter.current = mitt()
}
const childrenMap = React.useRef<ChildrenMapContextValue>(null)
if (childrenMap.current === null) {
childrenMap.current = new Map()
}
return (
<React.Suspense fallback={null}>
<EmitterContext.Provider value={emitter.current}>
<ChildrenMapContext.Provider value={childrenMap.current}>
<Children>
<Child duration={1}>Child A</Child>
<Child duration={2}>Child B</Child>
<Child duration={0.5}>Child C</Child>
</Children>
</ChildrenMapContext.Provider>
</EmitterContext.Provider>
</React.Suspense>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment