Last active
July 25, 2022 19:56
-
-
Save souporserious/3c812977ffbdff5e1d9956760daf18f7 to your computer and use it in GitHub Desktop.
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 * 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