diff --git a/packages/effect-components/src/ReactManagedRuntime.ts b/packages/effect-components/src/ReactManagedRuntime.ts index d964e94..0266b62 100644 --- a/packages/effect-components/src/ReactManagedRuntime.ts +++ b/packages/effect-components/src/ReactManagedRuntime.ts @@ -15,6 +15,7 @@ export const make = ( context: React.createContext>(null!), }) + export interface SyncProviderProps { readonly runtime: ReactManagedRuntime readonly children?: React.ReactNode @@ -27,3 +28,41 @@ export const SyncProvider = ( children: props.children, }) SyncProvider.displayName = "ReactManagedRuntimeSyncProvider" + + +export interface AsyncProviderProps extends React.SuspenseProps { + readonly runtime: ReactManagedRuntime + readonly children?: React.ReactNode +} + +export const 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 }), + ) +} +AsyncProvider.displayName = "AsyncProvider" + +interface AsyncProviderInnerProps { + readonly runtime: ReactManagedRuntime + readonly promise: Promise> + readonly children?: React.ReactNode +} + +const AsyncProviderInner = ( + { runtime, promise, children }: AsyncProviderInnerProps +): React.ReactNode => { + const value = React.use(promise) + + return React.createElement( + runtime.context, + { value }, + children, + ) +} +AsyncProviderInner.displayName = "AsyncProviderInner" diff --git a/packages/example/src/routes/effect-component-tests.tsx b/packages/example/src/routes/effect-component-tests.tsx index 3dadb32..055ff33 100644 --- a/packages/example/src/routes/effect-component-tests.tsx +++ b/packages/example/src/routes/effect-component-tests.tsx @@ -18,9 +18,9 @@ export const Route = createFileRoute("/effect-component-tests")({ function RouteComponent() { return ( - + - + ) }