Feliz icon indicating copy to clipboard operation
Feliz copied to clipboard

Component created with a forwardRef that has generic type parameters loses state

Open Jacques2Marais opened this issue 4 months ago • 0 comments

I have two components, GenericInputWithForwardRef and GenericInputWithoutForwardRef. Both these components have generic type parameters in the F# function definition. The first component also uses React.forwardRef in its definition. Here is the setup:

let GenericInputWithForwardRef<'t> = React.forwardRef (
   fun ((), ref) ->
      let value, setValue = React.useState ""
      Html.input [
         prop.value value
         prop.onChange setValue
         prop.ref ref
      ]
)

let GenericInputWithoutForwardRef<'t> () =
   let value, setValue = React.useState ""
   Html.input [
      prop.value value
      prop.onChange setValue
   ]

I then use these components as following

let refO = React.useRef None

React.fragment [
  GenericInputWithForwardRef ((), refO)
  GenericInputWithoutForwardRef ()
]

The problem is, whenever I change the value of the second component, the first component unmounts and mounts again, thus losing its state and value. After some debugging, I also realized that I forgot to add the [<ReactComponent>] attribute above the two component definitions. But doing this causes another issue:

image

Looking at the generated code on line 652 of FormTesting.fs.js, I see the following:

const xs = [createElement(GenericInputWithForwardRef, {})([void 0, refO]), createElement(GenericInputWithoutForwardRef, null)];
return react.createElement(react.Fragment, {}, ...xs);

And the error seems to be right after the part createElement(GenericInputWithForwardRef, {}) (the first create element). The generated code for GenericInputWithForwardRef is as following

export function GenericInputWithForwardRef() {
    return React_forwardRef_3790D881((tupledArg) => {
        const ref = tupledArg[1];
        const patternInput = useFeliz_React__React_useState_Static_1505("");
        const value = patternInput[0];
        const setValue = patternInput[1];
        return createElement("input", {
            value: value,
            onChange: (ev) => {
                setValue(ev.target.value);
            },
            ref: ref,
        });
    });
}

The issue seems to be perhaps with Feliz' implementation of React.forwardRef? Thank you.

Jacques2Marais avatar Mar 04 '24 08:03 Jacques2Marais