From 9a9bd78ec6f5a63db8567599c7ff01d2af1e8e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 28 Mar 2025 17:01:41 +0100 Subject: [PATCH] Provider work --- packages/reffuse/src/ReffuseContext.ts | 33 ++++++++++++++++---------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/reffuse/src/ReffuseContext.ts b/packages/reffuse/src/ReffuseContext.ts index 6467c68..b873724 100644 --- a/packages/reffuse/src/ReffuseContext.ts +++ b/packages/reffuse/src/ReffuseContext.ts @@ -1,4 +1,4 @@ -import { Array, Context, Effect, Layer, Ref, Runtime, Scope } from "effect" +import { Array, Context, Effect, Exit, Layer, Ref, Runtime, Scope } from "effect" import * as React from "react" import * as ReffuseRuntime from "./ReffuseRuntime.js" @@ -31,27 +31,36 @@ const makeProvider = (Context: React.Context>): ReactProvi return function ReffuseContextReactProvider(props) { const runtime = ReffuseRuntime.useRuntime() - const makeScopeAndContext = React.useMemo(() => Scope.make().pipe( - Effect.flatMap(scope => Effect.context().pipe( - Effect.map(context => [scope, context] as const), - + const makeScopeAndContext = React.useMemo(() => Effect.Do.pipe( + Effect.bind("scope", () => Scope.make()), + Effect.bind("context", ({ scope }) => Effect.context().pipe( Effect.provide(props.layer), Effect.provideService(Scope.Scope, scope), - )) + )), + Effect.map(({ scope, context }) => [scope, context] as const), ), [props.layer]) - const [initialScope, initialValue, isInitialRun] = React.useMemo(() => makeScopeAndContext.pipe( - Effect.flatMap(v => Ref.make(true).pipe( - Effect.map(isInitialRun => [...v, isInitialRun] as const) - )), + const [isInitialRun, initialScope, initialValue] = React.useMemo(() => Effect.Do.pipe( + Effect.bind("isInitialRun", () => Ref.make(true)), + Effect.bind("scopeAndContext", () => makeScopeAndContext), + Effect.map(({ isInitialRun, scopeAndContext }) => [isInitialRun, ...scopeAndContext] as const), Runtime.runSync(runtime), ), []) const [value, setValue] = React.useState(initialValue) - React.useEffect(() => { + React.useEffect(() => isInitialRun.pipe( + Effect.if({ + onTrue: () => Ref.set(isInitialRun, false), + onFalse: () => Effect.Do.pipe( + Effect.tap(Scope.close(initialScope, Exit.void)), + Effect.bind("scopeAndContext", () => makeScopeAndContext), + Effect.tap(({ scopeAndContext }) => Effect.sync(() => setValue())) + ), + }), - }, []) + Runtime.runSync(runtime), + ), [makeScopeAndContext, runtime]) return React.createElement(Context, { ...props, value }) }