```
The types above are pretty low level (basically the JS representation of a React component), but since ReScript React has its own ways of defining React components in a more language specific way, let's have a closer look on the anatomy of such a construct.
## JSX Component Interface
A ReScript React component needs to be a (sub-)module with a `make` function and `props` type to be usable in JSX. To make things easier, we provide a `@react.component` decorator to create those functions for you:
```res prelude
module Friend = {
@react.component
let make = (~name: string, ~age: int) => {React.string(name ++ ", " ++ age->Int.toString)}
}
module Container = {
@react.component
let make = (~width: int, ~children) => {<> {React.string(width->Int.toString)} children >}
}
```
```res example
module Friend = {
@react.component
let make = (~name: string, ~children) => {
{React.string(name)}
children
}
}
```
```res example
module Friend = {
type props<'name, 'children> = {
name: 'name,
children: 'children,
}
let make = ({name, children, _}: props) => {
ReactDOM.createDOMElementVariadic("div", [{React.string(name)}, children])
}
}
```
```js
function Playground$Friend(props) {
return JsxRuntime.jsxs("div", {
children: [
props.name,
props.children
]
});
}
var Friend = {
make: Playground$Friend
};
```
In the expanded output:
- `props`: A generated record type that has fields according to the labeled arguments of the `make` function
- `make`: A converted `make` function that complies to the component interface `(props) => React.element`
### Special Case React.forwardRef
The `@react.component` decorator also works for `React.forwardRef` calls:
```res
module FancyInput = {
@react.component
let make = React.forwardRef((~className=?, ~children, ref) =>
// use ref here
)
}
```
```res
// Simplified Output
type props<'className, 'children, 'ref> = {
className?: 'className,
children: 'children,
ref?: 'ref,
}
let make = (
{?className, children, _}: props<'className, 'children, ReactDOM.Ref.currentDomRef>,
ref: Nullable.t,
) => make(~className, ~children, ~ref, ())
```
As shown in the expanded output above, our decorator desugars the function passed to `React.forwardRef` in the same manner as a typical component `make` function. It also creates a `props` type with an optional `ref` field, so we can use it in our JSX call (``).
So now that we know how the ReScript React component transformation works, let's have a look on how ReScript transforms our JSX constructs.
## JSX Under the Hood
Whenever we are using JSX with a custom component ("capitalized JSX"), we are actually using `React.createElement` to create a new element. Here is an example of a React component without children:
```res example
let _ =
```
```res example
// classic
React.createElement(Friend.make, {name: "Fred", age:20})
// automatic
React.jsx(Friend.make, {name: "Fred", age: 20})
```
```js
JsxRuntime.jsx(Playground$Friend, { name: "Fred", age: 20 });
```
As you can see, it uses `Friend.make` to call the `React.createElement` API. In case you are providing children, it will use `React.createElementVariadic` instead (which is just a different binding for `React.createElement`):
```res example
{React.string("Hello")}
{React.string("World")}
```
```res example
// classic
React.createElementVariadic(
Container.make,
{width: 200, children: React.null},
[{React.string("Hello")}, {React.string("World")}],
)
// automatic
React.jsxs(
Container.make,
{width: 200, children: React.array([{React.string("Hello")}, {React.string("World")}])},
)
```
```js
JsxRuntime.jsx(Container, { width: 200, children: null }, "Hello", "World");
```
Note that the `children: React.null` field has no relevance since React will only care about the children array passed as a third argument.
### Dom Elements
"Uncapitalized JSX" expressions are treated as DOM elements and will be converted to `ReactDOM.createDOMElementVariadic` calls:
```res example
```
```res example
// classic
ReactDOM.createDOMElementVariadic("div", ~props={title: "test"}, [])
// automatic
ReactDOM.jsx("div", {title: "test"})
```
```js
JsxRuntime.jsx("div", { title: "test" });
```
The same goes for uncapitalized JSX with children:
```res example
```
```res example
// classic
ReactDOM.createDOMElementVariadic(
"div",
~props={title: "test"},
[ReactDOM.createDOMElementVariadic("span", [])],
)
// automatic
ReactDOM.jsx("div", {title: "test", children: ?ReactDOM.someElement(ReactDOM.jsx("span", {}))})
```
```js
JsxRuntime.jsx("div", {
children: JsxRuntime.jsx("span", {}),
title: "test"
});
```
```js
React.createElement("div", {
title: "test"
}, React.createElement("span", undefined));
```