Skip to content

[v3.0] Can dispose of optional IDisposables-test fails #655

@Freymaurer

Description

@Freymaurer

Test

testPromise "Can dispose of optional IDisposables" <| fun () -> promise {
        let render = RTL.render(OptionalDispose.render {| isSome = true |})

        Expect.toHaveTextContent (render.getByTestId("was-disposed")) "false" // "Should not be disposed yet"

        do! RTL.userEvent.click(render.getByTestId("dispose-button"))

        do!
            RTL.waitFor <| fun () ->
                Expect.toHaveTextContent (render.getByTestId("was-disposed")) "true" //"Should have been disposed"
    }

Summary

Checks if a react component unmounted with a React.useEffectOnce(fun () -> myIDisposable) triggers the _.Dispose() effect.

The test fails, it seems like the _.Dispose() function is not called.

Investigation

[<Hook>]
    let useEffectDisposableOptOnce (effect: unit -> #IDisposable option) =
        let destroyFunc = Interop.reactApi.useRefInternal None
        let calledOnce = Interop.reactApi.useRefInternal false
        let renderAfterCalled = Interop.reactApi.useRefInternal false

        if calledOnce.current then
            renderAfterCalled.current <- true

        useEffectDisposableOptWithDeps (fun () -> 
            if calledOnce.current 
            then None
            else
                calledOnce.current <- true
                destroyFunc.current <- effect()

                if renderAfterCalled.current
                then destroyFunc.current
                else None
        ) [||]

This is the main part of the function and to be honest: I have never used [<Hook>] before and have no idea why there are multiple internal refs here.

I had a quick look at the docs and came up with the following:

let useEffect (setup: System.Func<unit, (unit -> unit)>) = import "useEffect" "react"
let useEffectWithDisOpt (setup: unit -> System.IDisposable option) = 
    useEffect(System.Func<_,_>(fun () ->
        let dispose = setup()
        match dispose with
        | Some d -> fun () ->  d.Dispose()
        | None -> fun () -> ()
    ))

For which the test passes.

As i do not understand the original implementation i wanted to double check if this is fine @Zaid-Ajaj @MangelMaxime

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions