diff --git a/bun.lock b/bun.lock index 25eebc8..3271cdc 100644 --- a/bun.lock +++ b/bun.lock @@ -13,6 +13,9 @@ "packages/effect-fc": { "name": "effect-fc", "version": "0.1.0", + "dependencies": { + "@typed/async-data": "^0.13.1", + }, "devDependencies": { "@effect/language-service": "^0.23.3", }, diff --git a/packages/effect-fc/package.json b/packages/effect-fc/package.json index 157fe25..fdb3311 100644 --- a/packages/effect-fc/package.json +++ b/packages/effect-fc/package.json @@ -40,5 +40,8 @@ }, "devDependencies": { "@effect/language-service": "^0.23.3" + }, + "dependencies": { + "@typed/async-data": "^0.13.1" } } diff --git a/packages/effect-fc/src/Hook.ts b/packages/effect-fc/src/Hook.ts index b9fc28d..7ca508e 100644 --- a/packages/effect-fc/src/Hook.ts +++ b/packages/effect-fc/src/Hook.ts @@ -1,3 +1,4 @@ +import * as AsyncData from "@typed/async-data" import { type Context, Effect, ExecutionStrategy, Exit, type Layer, Option, pipe, PubSub, Ref, Runtime, Scope, Stream, SubscriptionRef } from "effect" import * as React from "react" import { SetStateAction } from "./types/index.js" @@ -196,6 +197,29 @@ export const useContextSync: { ), [scope]) }) +export const useContextAsync: { + ( + layer: Layer.Layer, + options?: ScopeOptions, + ): Effect.Effect, E>, never, Exclude> +} = Effect.fn("useContextAsync")(function* ( + layer: Layer.Layer, + options?: ScopeOptions, +) { + const [context, setContext] = React.useState, E>>(AsyncData.noData()) + + yield* useFork(() => Effect.sync(() => setContext(AsyncData.loading())).pipe( + Effect.andThen(Effect.provide(Effect.context(), layer)), + Effect.match({ + onSuccess: v => AsyncData.success(v), + onFailure: e => AsyncData.fail(e), + }), + Effect.andThen(setContext), + ), [layer], options) + + return context +}) + export const useRefFromReactiveValue: { (value: A): Effect.Effect>