import { Effect, type Layer, ManagedRuntime, type Runtime } from "effect" import * as React from "react" export interface ReactManagedRuntime { readonly runtime: ManagedRuntime.ManagedRuntime readonly context: React.Context> } export const make = ( layer: Layer.Layer, memoMap?: Layer.MemoMap, ): ReactManagedRuntime => ({ runtime: ManagedRuntime.make(layer, memoMap), context: React.createContext>(null!), }) export interface AsyncProviderProps extends React.SuspenseProps { readonly runtime: ReactManagedRuntime readonly children?: React.ReactNode } export function AsyncProvider( { runtime, children, ...suspenseProps }: AsyncProviderProps ): React.ReactNode { const promise = React.useMemo(() => Effect.runPromise(runtime.runtime.runtimeEffect), [runtime]) return React.createElement( React.Suspense, suspenseProps, React.createElement(AsyncProviderInner, { runtime, promise, children }), ) } interface AsyncProviderInnerProps { readonly runtime: ReactManagedRuntime readonly promise: Promise> readonly children?: React.ReactNode } function AsyncProviderInner( { runtime, promise, children }: AsyncProviderInnerProps ): React.ReactNode { const value = React.use(promise) return React.createElement(runtime.context, { value }, children) }