fable-compiler / fable-react

Fable bindings and helpers for React and React Native
MIT License
275 stars 67 forks source link

Add React.memo #112

Closed vbfox closed 5 years ago

vbfox commented 5 years ago

It also add to the helper types the concept of a ReactComponentType (Something that can be passed to createElement). Some of the types exists in the typescript-imported part of the library but they aren't really adapted and try to handle lot of things that are now obsolete.

They will also be necessary to import React.lazy

I didn't add any higher level helpers but one I find useful is the capability to create a named memo without passing the comparer :

let namedMemo<'props> (name: string) (f: 'props -> ReactElement): ReactComponentType<'props> =
    f?displayName <- name
    memo(f, None)

// Usage
type HelloProps = { Name: string }
let helloWorldComponent = namedMemo "HelloWorld" (fun props ->
  span [] [str "Hello "; str props.Name]
)
let helloWorld name = ofElementType helloWorldComponent { Name = name } []

Should I add it too ?

PS: No server-side rendering for now as I don't know how it should work.

Fixes #111

MangelMaxime commented 5 years ago

I think you should add the namedMemo function.

alfonsogarciacaro commented 5 years ago

Thanks @vbfox! Looks good :+1: I just left a couple of comments. It would be nice to have namedMemo too, although I'm not sure how to mix that with my proposal of having two functions memo and memoWith 🤔

alfonsogarciacaro commented 5 years ago

Another option could be to use a static type helper so we can use optional arguments (areEqual, name)... But I know @MangelMaxime doesn't like optional arguments XD

alfonsogarciacaro commented 5 years ago

Or a list of attributes in line with other React components:

memo [Name "foo"; AreEqual (fun p1 p2 -> p2.x = p2.x)] (fun props ->
   ...)
MangelMaxime commented 5 years ago

The list of attributes style is a bit more verbose, but like that we can have only one entry point for the function. I kind of like it :)

vbfox commented 5 years ago

After reflection I don't think that versions without name are useful for Fable developers, might as well guide people toward having a nicely named element tree.

I'll provide memo and memoWith with names.

vbfox commented 5 years ago
type HelloProps = { Name: string }

let helloWorldComponent = memo "HelloWorld" (fun props ->
  span [] [str "Hello "; str props.Name]
)
let helloWorld name = ofElementType helloWorldComponent { Name = name } []

let helloWorldComponent2 = memoWith "HelloWorld" (fun a b -> a.Name = b.Name) (fun props ->
  span [] [str "Hello "; str props.Name]
)
let helloWorld2 name = ofElementType helloWorldComponent2 { Name = name } []
alfonsogarciacaro commented 5 years ago

Awesome, thanks a lot!

alfonsogarciacaro commented 5 years ago

I've published this as Fable.React 5.0.0-alpha-001 (at the end I used memoBuilder for the name, sorry!). I've also tried to adapt it to SSR, @forki can you please give it a try? Thanks!