Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attribute to compile arguments as JS object #1622

Closed
alfonsogarciacaro opened this issue Oct 30, 2018 · 3 comments
Closed

Attribute to compile arguments as JS object #1622

alfonsogarciacaro opened this issue Oct 30, 2018 · 3 comments

Comments

@alfonsogarciacaro
Copy link
Member

The new additions to React (memo, hooks) indicates the community is going to move more towards functions as components rather than classes. This is good news for us, because the class syntax in F# is a bit verbose for this purpose. However, there are still things we can do to improve the experience.

At FableConf @vbfox suggested to enable an attribute to compile arguments as a JS object, so we don't need to declare a record every time we want to define a function component with props. So instead of:

type MyProps = { key: string; value1: int; value2: float[] }

let MyComponent (props: MyProps) =
    div [] [...]

// Use
ofFunction MyComponent { key = "foo"; value1 = 5; value2 = [] } []

We could write:

let [<MagicAttribute>] MyComponent (key: string) (value1: int) (value2: float[]) () =
    div [] [...]

// Use?
ofFunction2 (MyComponent "foo" 5 []) []

I just noticed we forgot to discuss how this would be called. In the sample above I just added a unit argument at the end to prevent execution, but there may be other ways.

In principle, I wanted to avoid magic attributes in F# as much as possible, but it could be justified in this case. An alternative could be to just wait until anonymous records come into F#. They may solve this situation and we would align to standard F#, and it seems they will be early in F# previews.

@Zaid-Ajaj
Copy link
Member

An alternative could be to just wait until anonymous records come into F#

Since the issue is already addressed on the F# part of things and there is already an alternative in Fable by defining a record, I would suggest to wait until we have anonymous records. Otherwise you will only add a feature that will be removed in the near future, not to mention that it must be implemented, tested, documented , added with some examples and users will need to learn yet another attribute next to their arsenal of Fable quirks that do javascripty things

@MangelMaxime
Copy link
Member

I am in favor for waiting anonymous F# record

@vbfox
Copy link
Contributor

vbfox commented Oct 30, 2018

Anonymous records are still pretty verbose :

// Declaration
let userView = namedMemo "User" (fun ({| UserId: string; Name: string |}) ->
    a [Href (sprintf "/%s/" props.UserId)] [str props.Name])

// Usage
ofElementType userView { UserId = "vbfox"; Name = "Julien Roncaglia" } []

Normal records :

// Declaration
type UserViewProps = { UserId: string; Name: string }
let userView = namedMemo "User" (fun props ->
    a [Href (sprintf "/%s/" props.UserId)] [str props.Name])

// Usage
ofElementType userView { UserId = "vbfox"; Name = "Julien Roncaglia" } []

But the more I think about my proposal the more I see problems with it... Even with such a primitive it would allow for functional components to work but not wrapped ones like memo as the argument names would be lost from the compiler :( :( :(

I think you can close this @alfonsogarciacaro I'll reopen one if I find a way to solve this... For now we'll create records or tuples XD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants