Fable icon indicating copy to clipboard operation
Fable copied to clipboard

Do we have access to the `ParamObject` information from Fable plugins?

Open MangelMaxime opened this issue 3 years ago • 1 comments

Description

Sometimes when using React you need to pass a component and that's the a library which is going to fill the props values.

One solution when doing so is to use unbox {||} to generate the right JavaScript.

[<ReactComponent>]
let MyApp () =
    reactResizeDetector.reactResizeDetector [
        reactResizeDetector.handleHeight
        reactResizeDetector.handleWidth
        prop.children (Content (unbox {||}))
    ]

One solution that I found could be to use ParamObject which implements the interface contract

[<Global>]
type MyProps [<ParamObject; Emit "$0">]
    (
        ?height: float,
        ?width: float,
        ?targetRef : IRefValue<Browser.Types.HTMLDivElement>
    )
    =
    member val height: float = jsNative with get
    member val width: float = jsNative with get
    member val targetRef : IRefValue<Browser.Types.HTMLDivElement> = jsNative with get

    interface ChildFunctionProps<Browser.Types.HTMLDivElement> with

        member this.height
            with get() = height

        member this.width
            with get() = width

        member this.targetRef
            with get() = targetRef

which allows for a much cleaner caller code:

reactResizeDetector.reactResizeDetector [
    reactResizeDetector.handleHeight
    reactResizeDetector.handleWidth
    prop.children (Content (MyProps()))
]

However as it is now ReactComponent is rewritting the properties access instead of keeping the props as it is

export function ChildFunction_Content(childFunction_ContentInputProps) {
    const props = childFunction_ContentInputProps.props;
    // ...
}

// Instead of
export function ChildFunction_Content(props) {
    // ...
}

Before diving into ReactComponent code, I wanted to ask if we had access to the attributes attach to the type when within a Fable plugin and more specifically ReactComponent?

The idea is to detect ParamObject usage to not rewrite the properties in this case.

MangelMaxime avatar Apr 12 '22 13:04 MangelMaxime

It's possible though not very ergonomic at the moment. You probably need to do the same as Fable does, try to retrieve the declaring entity from CallMemberInfo, then identify the method that is being called and then check the attributes:

https://github.com/fable-compiler/Fable/blob/1da89fe30f787129f5d3648b75152feb5c603771/src/Fable.Transforms/Fable2Babel.fs#L1134-L1176

In Snake Island (Fable 4 codename) I'm adding a IsNamed property to the arguments to make this easier.

alfonsogarciacaro avatar Apr 13 '22 07:04 alfonsogarciacaro