Open leolorenzoluis opened 5 years ago
Neither, it's an F# thing ;) Generic values are actually compiled as functions and the code is evaluated each time the value is called. If you try the following snippet in F# Interactive, "foo" will be printed two times:
let foo<'T> = printfn "foo"; 5
foo + foo
I acknowledge it's confusing and the need to use generic values if you want to use a generic type in the props makes it unfortunately even more confusing (I also discovered this recently). It's possible to use a generic property if you just use a plain function and instantiate that with ofFunction
. But in order to use memoize
(which calls React.memo
under the hood) you need a value reference, which for generics has the behavior shown above in F#:
let render (props: {| value: 'T |}) = ...
ofFunction render {| value = 5 |} [] // This works
let MyComponent<'T> =
FunctionComponent.Of((fun (props: {| value: 'T |}) -> ...), memoizeWith=equalsButFunctions)
MyComponent {| value = 5 |} // This creates a new component every time, not the desired behavior
To overcome this, the only solution for now is to create an intermediate function that makes a concrete React component out of the generic function, like this:
let render<'T> (props: {| value: 'T |}) = str ""
let makeComponent<'T>() =
FunctionComponent.Of(render<'T>, memoizeWith=equalsButFunctions)
let MyIntComponent = makeComponent<int>()
MyIntComponent {| value = 5 |} // The component is memoized as expected
Given I have the following code
The memoizeWith callback is not called, and for some reason the function keeps getting called infinitely.
If I change it to a non generic then it works fine
Not sure if this is an issue with Fable or React.