[JSX] Improve JSX "detection" for function call
Issue
Currently if a function is not decorated with the [<JSX.ComponentAttribute>], it will be called as function and not JSX.Component. For Feliz this is a rather breaking change as you only had to decorate functions using React with the [<ReactComponent>] attribute. It would be nice to improve detection of JSX.Element to automatically refer to it with Component Syntax.
The following code showcases this
// [<JSX.ComponentAttribute>]
let Component1 () =
JSX.create "div" [
"id", "InnerId"
"children", "Hello World!"
]
let Component2() =
JSX.create "div" [
"children", [
box "Title"
box 12
Component1() |> box
]
]
Output:
// with [<JSX.ComponentAttribute>]
export function Component1() {
return <div id="InnerId">
Hello World!
</div>;
}
export function Component2() {
return <div>
Title
{12}
<Component1></Component1>
</div>;
}
// without [<JSX.ComponentAttribute>]
export function Component1() {
return <div id="InnerId">
Hello World!
</div>;
}
export function Component2() {
return <div>
Title
{12}
{Component1()}
</div>;
}
Alternative Example
The example above can be avoided by using the attribute, but here is an example with a subcomponent defined inside the main component for better readability:
[<JSX.ComponentAttribute>]
let Component2() =
let subcomponent() =
JSX.create "div" [
"id", "InnerId"
"children", "Hello World!"
]
JSX.create "div" [
"children", [
box "Title"
box 12
subcomponent() |> box
]
]
And output:
export function Component2() {
const subcomponent = () => <div id="InnerId">
Hello World!
</div>;
return <div>
Title
{12}
{subcomponent()}
</div>;
}
This isn't an issue in Solid-js, as components are just function calls.
For me personally, I think this is correct. Better that component rendering is explicit rather than implicit and potentially breaking.
For Feliz this is a rather breaking change as you only had to decorate functions using React with the
[<ReactComponent>]attribute
To be more precise, we needed [<ReactComponent>] when we wanted to use React API to access hooks and stuff like that. Or follow React philosophy of using props for passing information instead of arguments.
It is also possible that by generating {subcomponent()} React tooling will not report the component in the dev tool DOM.
I remember that in some cases generating code like {subcomponent()} was difficult with Feliz so perhaps we should be careful about not removing a feature we could need in the future.
I am not 100% certain yet of what should be decided here.
An operator or function could be introduced which forces a function call that outputs a JSX.Element to compile as a tag.
You could then create a helper that combines that with box (since there is already element decoration in the example).
This seems like a Plugin thing though
An operator or function could be introduced which forces a function call that outputs a
JSX.Elementto compile as a tag.
[<JSX.ComponentAttribute>] seems to be doing that even if it rewrites the function from:
function MyComponent(arg1, arg2)
to
function MyComponent(props) {
// Usage
// props.arg1
// props.arg2
}
I don't think it matters much if the argument are rewritten to a props objects.
Indeed, but I think Freymauer wants to avoid explicit decoration of a function that should be compiled as a tag.
To clarify though, I am 100% for explicit decoration over implicit conversion. This is why I think, if people wanted a more concise/implicit conversion, it would be better suited to a plugin to resolve, rather than introduced as implicit behaviour for JSX.
ie: my opinion is this is not an 'issue', and is instead correct output.