1+ import * as Option from "@effect/data/Option"
12import * as Effect from "@effect/io/Effect"
2- import * as Exit from "@effect/io/Exit"
33import * as Fiber from "@effect/io/Fiber"
4- import * as Ref from "@effect/io/Ref"
54import * as Runtime from "@effect/io/Runtime"
65import * as Stream from "@effect/stream/Stream"
76import type { ResultBag } from "effect-react/hooks/useResultBag"
87import { updateNext , useResultBag } from "effect-react/hooks/useResultBag"
98import type { RuntimeContext } from "effect-react/internal/runtimeContext"
109import * as Result from "effect-react/Result"
11- import { useCallback , useContext , useEffect , useRef , useState } from "react"
12-
13- type FiberState < E > = { readonly _tag : "Idle" } | {
14- readonly _tag : "Running"
15- readonly fiber : Fiber . RuntimeFiber < E , void >
16- readonly interruptingRef : Ref . Ref < boolean >
17- }
10+ import { useCallback , useContext , useEffect , useState } from "react"
1811
1912export type UseResultCallback < R > = < Args extends Array < any > , R0 extends R , E , A > (
2013 callback : ( ...args : Args ) => Effect . Effect < R0 , E , A >
@@ -32,57 +25,40 @@ export const makeUseResultCallback: <R>(
3225 const [ trackRef , resultBag ] = useResultBag ( result )
3326 trackRef . current . currentStatus = result . _tag
3427
35- const fiberState = useRef < FiberState < E > > ( { _tag : "Idle" } )
36- useEffect ( ( ) =>
37- ( ) => {
38- if ( fiberState . current . _tag === "Running" ) {
39- Effect . runSync ( Ref . set ( fiberState . current . interruptingRef , true ) )
40- Effect . runFork ( Fiber . interruptFork ( fiberState . current . fiber ) )
41- }
42- } , [ ] )
43-
4428 const runtime = useContext ( runtimeContext )
45- const run = useCallback ( ( ... args : Args ) => {
46- if ( fiberState . current . _tag === "Running" ) {
47- Effect . runSync ( Ref . set ( fiberState . current . interruptingRef , true ) )
48- Effect . runFork ( Fiber . interruptFork ( fiberState . current . fiber ) )
29+ const [ currentArgs , setCurrentArgs ] = useState < Option . Option < Args > > ( Option . none ( ) )
30+ useEffect ( ( ) => {
31+ if ( Option . isNone ( currentArgs ) ) {
32+ return
4933 }
5034
51- trackRef . current . invocationCount ++
52-
53- const interruptingRef = Ref . unsafeMake ( false )
35+ let interrupting = false
5436 const maybeSetResult = ( result : Result . Result < E , A > | ( ( _ : Result . Result < E , A > ) => Result . Result < E , A > ) ) =>
55- Effect . flatMap (
56- Ref . get ( interruptingRef ) ,
57- ( interrupting ) =>
58- interrupting ? Effect . unit : Effect . sync ( ( ) => {
59- setResult ( result )
60- } )
61- )
37+ Effect . sync ( ( ) => {
38+ if ( ! interrupting ) {
39+ setResult ( result )
40+ }
41+ } )
6242
6343 const fiber = Stream . suspend ( ( ) => {
6444 setResult ( ( prev ) => updateNext ( Result . waiting ( prev ) , trackRef ) )
65- return f ( ...args )
45+ return f ( ...currentArgs . value )
6646 } ) . pipe (
6747 Stream . tap ( ( value ) => maybeSetResult ( updateNext ( Result . success ( value ) , trackRef ) ) ) ,
6848 Stream . tapErrorCause ( ( cause ) => maybeSetResult ( updateNext ( Result . failCause ( cause ) , trackRef ) ) ) ,
6949 Stream . runDrain ,
70- Effect . onExit ( ( exit ) =>
71- Exit . isInterrupted ( exit )
72- ? Effect . unit
73- : Effect . sync ( ( ) => {
74- fiberState . current = { _tag : "Idle" }
75- } )
76- ) ,
7750 Runtime . runFork ( runtime )
7851 )
7952
80- fiberState . current = {
81- _tag : "Running" ,
82- fiber,
83- interruptingRef
53+ return ( ) => {
54+ interrupting = true
55+ Effect . runFork ( Fiber . interruptFork ( fiber ) )
8456 }
85- } , [ f ] )
57+ } , [ currentArgs ] )
58+
59+ const run = useCallback ( ( ...args : Args ) => {
60+ setCurrentArgs ( Option . some ( args ) )
61+ } , [ ] )
8662
8763 return [ resultBag , run ] as const
8864 }
0 commit comments