From c91b538c973249f44a9b62e99816d1a0d0e2151d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 9 Jan 2025 14:27:41 +0100 Subject: [PATCH] Reffuse work --- packages/reffuse/src/Reffuse.ts | 40 +++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/reffuse/src/Reffuse.ts b/packages/reffuse/src/Reffuse.ts index 396eeea..f61c33d 100644 --- a/packages/reffuse/src/Reffuse.ts +++ b/packages/reffuse/src/Reffuse.ts @@ -1,6 +1,6 @@ -import { Effect, Exit, Fiber, ManagedRuntime, Stream, SubscriptionRef } from "effect" +import { Effect, Exit, Fiber, ManagedRuntime, Ref, Stream, SubscriptionRef } from "effect" import type { RunForkOptions } from "effect/Runtime" -import React, { useMemo } from "react" +import React from "react" export class Reffuse { @@ -9,17 +9,16 @@ export class Reffuse { private readonly runtime: ManagedRuntime.ManagedRuntime ) { this.Context = React.createContext(runtime) - } - readonly Context: React.Context> - - Provider(props: { readonly children: React.ReactNode }) { - return this.Context.Provider({ + this.Provider = (props: { readonly children?: React.ReactNode }) => this.Context.Provider({ ...props, value: this.runtime, }) } + readonly Context: React.Context> + readonly Provider: React.FC<{ readonly children?: React.ReactNode }> + useRuntime(): ManagedRuntime.ManagedRuntime { return React.useContext(this.Context) @@ -62,20 +61,33 @@ export class Reffuse { options?: RunForkOptions, ): void { return React.useEffect(() => { - const fiber = this.runFork(self, options) + const fiber = this.runFork(self.pipe(Effect.scoped), options) return () => { this.runFork(Fiber.interrupt(fiber)) } }, deps) } - useRefState(ref: SubscriptionRef.SubscriptionRef) { - const initial = useMemo(() => this.runSync(ref), [ref]) - const [value, setValueInternal] = React.useState(initial) + + useRef(value: A): SubscriptionRef.SubscriptionRef { + return React.useMemo(() => this.runSync(SubscriptionRef.make(value)), []) + } + + useRefState(ref: SubscriptionRef.SubscriptionRef): [A, React.Dispatch>] { + const initialState = React.useMemo(() => this.runSync(ref), [ref]) + const [reactStateValue, setReactStateValue] = React.useState(initialState) this.useFork(Stream.runForEach(ref.changes, v => Effect.sync(() => - setValueInternal(v) - ))) + setReactStateValue(v) + )), [ref]) - return [] + const setValue = React.useCallback((setStateAction: React.SetStateAction) => + this.runSync(Ref.update(ref, previousState => + typeof setStateAction === "function" + ? (setStateAction as (prevState: A) => A)(previousState) + : setStateAction + )), + [ref]) + + return [reactStateValue, setValue] } }