diff --git a/packages/effect-components/src/ReactComponent.ts b/packages/effect-components/src/ReactComponent.ts
index 118b6ac..6960543 100644
--- a/packages/effect-components/src/ReactComponent.ts
+++ b/packages/effect-components/src/ReactComponent.ts
@@ -7,71 +7,48 @@ export interface ReactComponent
{
(props: P): Effect.Effect
}
+export const nonReactiveTags = [Tracer.ParentSpan] as const
+
export const useFC: {
(
self: ReactComponent
,
options?: ReactHook.ScopeOptions,
): Effect.Effect, never, Exclude>
-} = Effect.fn(function* useFC(
+} = Effect.fnUntraced(function* useFC
(
self: ReactComponent
,
options?: ReactHook.ScopeOptions,
) {
const runtime = yield* Effect.runtime>()
- return React.useCallback((props: P) => Runtime.runSync(runtime)(
- self(props) as Effect.Effect>
- ), [])
+ return React.useCallback((props: P) => {
+ const [isInitialRun, initialScope] = React.useMemo(() => Runtime.runSync(runtime)(
+ Effect.all([Ref.make(true), makeScope(options)])
+ ), [])
+ const [scope, setScope] = React.useState(initialScope)
+
+ React.useEffect(() => Runtime.runSync(runtime)(
+ Effect.if(isInitialRun, {
+ onTrue: () => Effect.as(
+ Ref.set(isInitialRun, false),
+ () => closeScope(scope, runtime, options),
+ ),
+
+ onFalse: () => makeScope(options).pipe(
+ Effect.tap(scope => Effect.sync(() => setScope(scope))),
+ Effect.map(scope => () => closeScope(scope, runtime, options)),
+ ),
+ })
+ ), [])
+
+ return Runtime.runSync(runtime)(
+ Effect.provideService(self(props), Scope.Scope, scope)
+ )
+ }, Array.from(
+ Context.omit(...nonReactiveTags)(runtime.context).unsafeMap.values()
+ ))
})
-export const use: {
- (
- self: ReactComponent
,
- fn: (Component: React.FC
) => React.ReactNode,
- options?: ReactHook.ScopeOptions,
- ): Effect.Effect>
-} = Effect.fn(function* use(
- self: ReactComponent
,
- fn: (Component: React.FC
) => React.ReactNode,
- options?: ReactHook.ScopeOptions,
-) {
- return fn(yield* useFC(self, options))
-})
-
-
-const FC =
(
- self: ReactComponent
,
- runtime: Runtime.Runtime,
- props: P,
- options?: ReactHook.ScopeOptions,
-): React.ReactNode => {
- const [isInitialRun, initialScope] = React.useMemo(() => Runtime.runSync(runtime)(
- Effect.all([Ref.make(true), makeScope(options)])
- ), [])
- const [scope, setScope] = React.useState(initialScope)
-
- React.useEffect(() => Runtime.runSync(runtime)(
- Effect.if(isInitialRun, {
- onTrue: () => Effect.as(
- Ref.set(isInitialRun, false),
- () => closeScope(scope, runtime, options),
- ),
-
- onFalse: () => makeScope(options).pipe(
- Effect.tap(scope => Effect.sync(() => setScope(scope))),
- Effect.map(scope => () => closeScope(scope, runtime, options)),
- ),
- })
- ), [])
-
- return React.useMemo(() => Runtime.runSync(runtime)(
- Effect.provideService(self(props), Scope.Scope, scope)
- ), [
- props,
- ...Array.from(Context.omit(Tracer.ParentSpan)(runtime.context).unsafeMap.values()),
- ])
-}
-
const makeScope = (options?: ReactHook.ScopeOptions) => Scope.make(options?.finalizerExecutionStrategy ?? ExecutionStrategy.sequential)
const closeScope = (
scope: Scope.CloseableScope,
@@ -87,3 +64,17 @@ const closeScope = (
break
}
}
+
+export const use: {
+ (
+ self: ReactComponent
,
+ fn: (Component: React.FC
) => React.ReactNode,
+ options?: ReactHook.ScopeOptions,
+ ): Effect.Effect>
+} = Effect.fnUntraced(function* use(
+ self: ReactComponent
,
+ fn: (Component: React.FC
) => React.ReactNode,
+ options?: ReactHook.ScopeOptions,
+) {
+ return fn(yield* useFC(self, options))
+})
diff --git a/packages/example/src/routes/effect-component-tests.tsx b/packages/example/src/routes/effect-component-tests.tsx
index 9284220..d95daa1 100644
--- a/packages/example/src/routes/effect-component-tests.tsx
+++ b/packages/example/src/routes/effect-component-tests.tsx
@@ -15,9 +15,7 @@ function RouteComponent() {
return <>
{runtime.runSync(ReactComponent.use(MyTestComponent, Component => (
- )).pipe(
- Effect.scoped
- ))}
+ )))}
>
}
@@ -30,10 +28,10 @@ const MyTestComponent = Effect.fn(function* MyTestComponent(props?: { readonly v
const [state, setState] = React.useState("value")
const effectValue = yield* Effect.succeed(`state: ${ state }`)
- yield* ReactHook.useOnce(() => Effect.andThen(
+ yield* ReactHook.useEffect(() => Effect.andThen(
Effect.addFinalizer(() => Console.log("MyTestComponent umounted")),
Console.log("MyTestComponent mounted"),
- ))
+ ), [])
return <>
{effectValue}