diff --git a/packages/reffuse/src/ReffuseContext.tsx b/packages/reffuse/src/ReffuseContext.tsx deleted file mode 100644 index 89d1394..0000000 --- a/packages/reffuse/src/ReffuseContext.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { Array, Context, Effect, Layer, Runtime } from "effect" -import * as React from "react" -import * as ReffuseRuntime from "./ReffuseRuntime.js" - - -export class ReffuseContext { - readonly Context = React.createContext>(null!) - readonly Provider = makeProvider(this.Context) - readonly AsyncProvider = makeAsyncProvider(this.Context) - - - useContext(): Context.Context { - return React.useContext(this.Context) - } - - useLayer(): Layer.Layer { - const context = this.useContext() - return React.useMemo(() => Layer.effectContext(Effect.succeed(context)), [context]) - } -} - -export type R = T extends ReffuseContext ? R : never - - -export type ReactProvider = React.FC<{ - readonly layer: Layer.Layer - readonly children?: React.ReactNode -}> - -function makeProvider(Context: React.Context>): ReactProvider { - return function ReffuseContextReactProvider(props) { - const runtime = ReffuseRuntime.useRuntime() - - const value = React.useMemo(() => Effect.context().pipe( - Effect.provide(props.layer), - Runtime.runSync(runtime), - ), [props.layer, runtime]) - - return ( - - ) - } -} - -export type AsyncReactProvider = React.FC<{ - readonly layer: Layer.Layer - readonly fallback?: React.ReactNode - readonly children?: React.ReactNode -}> - -function makeAsyncProvider(Context: React.Context>): AsyncReactProvider { - function Inner({ promise, children }: { - readonly promise: Promise> - readonly children?: React.ReactNode - }) { - const value = React.use(promise) - - return ( - - ) - } - - return function ReffuseContextAsyncReactProvider(props) { - const runtime = ReffuseRuntime.useRuntime() - - const promise = React.useMemo(() => Effect.context().pipe( - Effect.provide(props.layer), - Runtime.runPromise(runtime), - ), [props.layer, runtime]) - - return ( - - - - ) - } -} - - -export function make() { - return new ReffuseContext() -} - -export function useMergeAll>( - ...contexts: [...{ [K in keyof T]: ReffuseContext }] -): Context.Context { - const values = contexts.map(v => React.use(v.Context)) - return React.useMemo(() => Context.mergeAll(...values), values) -} - -export function useMergeAllLayers>( - ...contexts: [...{ [K in keyof T]: ReffuseContext }] -): Layer.Layer { - const values = contexts.map(v => React.use(v.Context)) - - return React.useMemo(() => Array.isNonEmptyArray(values) - ? Layer.mergeAll( - ...Array.map(values, context => Layer.effectContext(Effect.succeed(context))) - ) - : Layer.empty as Layer.Layer, - values) -} diff --git a/packages/reffuse/src/ReffuseRuntime.ts b/packages/reffuse/src/ReffuseRuntime.ts new file mode 100644 index 0000000..47e22b0 --- /dev/null +++ b/packages/reffuse/src/ReffuseRuntime.ts @@ -0,0 +1,15 @@ +import { Runtime } from "effect" +import * as React from "react" + + +export const Context = React.createContext>(null!) + +export const Provider = (props: { + readonly children?: React.ReactNode +}) => React.createElement(Context, { + ...props, + value: Runtime.defaultRuntime, +}) +Provider.displayName = "ReffuseRuntimeReactProvider" as const + +export const useRuntime = () => React.useContext(Context) diff --git a/packages/reffuse/src/ReffuseRuntime.tsx b/packages/reffuse/src/ReffuseRuntime.tsx deleted file mode 100644 index 3a6c75e..0000000 --- a/packages/reffuse/src/ReffuseRuntime.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Runtime } from "effect" -import * as React from "react" - - -export const Context = React.createContext>(null!) - -export const Provider = (props: { readonly children?: React.ReactNode }) => ( - -) -Provider.displayName = "ReffuseRuntimeReactProvider" - -export const useRuntime = () => React.useContext(Context)