diff --git a/packages/effect-fc/src/Component.ts b/packages/effect-fc/src/Component.ts index 9536427..39bd6dd 100644 --- a/packages/effect-fc/src/Component.ts +++ b/packages/effect-fc/src/Component.ts @@ -1,6 +1,6 @@ /** biome-ignore-all lint/complexity/noBannedTypes: {} is the default type for React props */ /** biome-ignore-all lint/complexity/useArrowFunction: necessary for class prototypes */ -import { Context, Effect, Effectable, ExecutionStrategy, Exit, Fiber, Function, HashMap, Layer, ManagedRuntime, Option, Predicate, Ref, Runtime, Scope, Tracer, type Types, type Utils } from "effect" +import { Context, Effect, Effectable, Equivalence, ExecutionStrategy, Exit, Fiber, Function, HashMap, Layer, ManagedRuntime, Option, Predicate, Ref, Runtime, Scope, Tracer, type Types, type Utils } from "effect" import * as React from "react" import { Memoized } from "./index.js" @@ -61,14 +61,16 @@ const ComponentProto = Object.freeze({ const runtimeRef = React.useRef>>(null!) runtimeRef.current = yield* Effect.runtime>() - 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( + return yield* React.useState(() => Runtime.runSync(runtimeRef.current)(Effect.cachedFunction( + (_services: readonly any[]) => Effect.sync(() => { + const f: React.FC

= this.makeFunctionComponent(runtimeRef) + f.displayName = this.displayName ?? "Anonymous" + return Memoized.isMemoized(this) + ? React.memo(f, this.propsAreEqual) + : f + }), + Equivalence.array(Equivalence.strict()), + )))[0](Array.from( Context.omit(...nonReactiveTags)(runtimeRef.current.context).unsafeMap.values() )) }), @@ -406,11 +408,7 @@ export const withRuntime: { export class ScopeMap extends Effect.Service()("effect-fc/Component/ScopeMap", { - effect: Effect.bind( - Effect.Do, - "ref", - () => Ref.make(HashMap.empty()), - ), + effect: Effect.bind(Effect.Do, "ref", () => Ref.make(HashMap.empty())) }) {} export namespace ScopeMap { diff --git a/packages/example/src/routes/form.tsx b/packages/example/src/routes/form.tsx index ea5d233..30fe641 100644 --- a/packages/example/src/routes/form.tsx +++ b/packages/example/src/routes/form.tsx @@ -92,7 +92,7 @@ class RegisterFormView extends Component.makeUntraced("RegisterFormView")(functi const RegisterPage = Component.makeUntraced("RegisterPage")(function*() { const RegisterFormViewFC = yield* Effect.provide( RegisterFormView, - yield* Component.useContext(RegisterForm.Default, { finalizerExecutionMode: "fork" }), + yield* Component.useContext(RegisterForm.Default), ) return diff --git a/packages/example/src/routes/index.tsx b/packages/example/src/routes/index.tsx index d87902d..f9146cc 100644 --- a/packages/example/src/routes/index.tsx +++ b/packages/example/src/routes/index.tsx @@ -11,7 +11,7 @@ const TodosStateLive = TodosState.Default("todos") const Index = Component.makeUntraced("Index")(function*() { const TodosFC = yield* Effect.provide( Todos, - yield* Component.useContext(TodosStateLive, { finalizerExecutionMode: "fork" }), + yield* Component.useContext(TodosStateLive), ) return