diff --git a/packages/effect-fc/src/Async.ts b/packages/effect-fc/src/Async.ts index 19c1912..c9f1a2a 100644 --- a/packages/effect-fc/src/Async.ts +++ b/packages/effect-fc/src/Async.ts @@ -1,10 +1,10 @@ /** biome-ignore-all lint/complexity/useArrowFunction: necessary for class prototypes */ import { Effect, Function, Predicate, Runtime, Scope } from "effect" import * as React from "react" -import type * as Component from "./Component.js" +import * as Component from "./Component.js" -export const TypeId: unique symbol = Symbol.for("effect-fc/Async") +export const TypeId: unique symbol = Symbol.for("effect-fc/Async/Async") export type TypeId = typeof TypeId export interface Async extends Async.Options { @@ -26,13 +26,15 @@ const SuspenseProto = Object.freeze({ makeFunctionComponent

( this: Component.Component & Async, runtimeRef: React.RefObject>>, - scope: Scope.Scope, ) { const SuspenseInner = (props: { readonly promise: Promise }) => React.use(props.promise) return ({ fallback, name, ...props }: Async.Props) => { const promise = Runtime.runPromise(runtimeRef.current)( - Effect.provideService(this.body(props as P), Scope.Scope, scope) + Effect.andThen( + Component.useScope([], this), + scope => Effect.provideService(this.body(props as P), Scope.Scope, scope), + ) ) return React.createElement( diff --git a/packages/effect-fc/src/Component.ts b/packages/effect-fc/src/Component.ts index 34f6b43..f7d1881 100644 --- a/packages/effect-fc/src/Component.ts +++ b/packages/effect-fc/src/Component.ts @@ -25,8 +25,7 @@ extends /** @internal */ makeFunctionComponent( - runtimeRef: React.Ref>>, - scope: Scope.Scope, + runtimeRef: React.Ref>> ): (props: P) => A } @@ -58,38 +57,31 @@ const ComponentProto = Object.freeze({ commit: Effect.fnUntraced(function*

( this: Component ) { - const self = this // biome-ignore lint/style/noNonNullAssertion: React ref initialization const runtimeRef = React.useRef>>(null!) runtimeRef.current = yield* Effect.runtime>() - return React.useRef(function ScopeProvider(props: P) { - const scope = Runtime.runSync(runtimeRef.current)(useScope( - Array.from( - Context.omit(...nonReactiveTags)(runtimeRef.current.context).unsafeMap.values() - ), - self, - )) - - const FC = React.useMemo(() => { - const f: React.FC

= self.makeFunctionComponent(runtimeRef, scope) - f.displayName = self.displayName ?? "Anonymous" - return Memoized.isMemoized(self) - ? React.memo(f, self.propsAreEqual) - : f - }, [scope]) - - return React.createElement(FC, props) - }).current + return React.useMemo(() => { + const f: React.FC

= this.makeFunctionComponent(runtimeRef) + f.displayName = this.displayName ?? "Anonymous" + return Memoized.isMemoized(this) + ? React.memo(f, this.propsAreEqual) + : f + // biome-ignore lint/correctness/useExhaustiveDependencies: Effect context comparison + }, Array.from( + Context.omit(...nonReactiveTags)(runtimeRef.current.context).unsafeMap.values() + )) }), makeFunctionComponent

( this: Component, runtimeRef: React.RefObject>>, - scope: Scope.Scope, ) { return (props: P) => Runtime.runSync(runtimeRef.current)( - Effect.provideService(this.body(props), Scope.Scope, scope) + Effect.andThen( + useScope([], this), + scope => Effect.provideService(this.body(props), Scope.Scope, scope), + ) ) }, } as const)