You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
summary: "This is the `@jsx.component` decorator."
6
+
category: "decorators"
7
+
---
8
+
9
+
**Since 11.1**
10
+
11
+
The `@jsx.component` decorator is used to annotate functions that are [JSX](/docs/react/latest/elements-and-jsx) components. This is a _generic_ version that's equivalent to the existing `@react.component` for React.
12
+
13
+
You will need this decorator whenever you want to use JSX component in JSX expressions, with a [generic JSX transform](/docs/manual/latest/jsx#generic-jsx-transform-jsx-beyond-react-experimental) configured.
14
+
15
+
16
+
### Example
17
+
18
+
<CodeTablabels={["ReScript", "JS Output"]}>
19
+
20
+
```res
21
+
// Assuming `Preact` is set up and configured as a generic JSX transform.
22
+
@jsx.component
23
+
let make = (~name) => {
24
+
<button> {Preact.string("Hello " ++ name ++ "!")} </button>
Copy file name to clipboardExpand all lines: pages/docs/manual/latest/jsx.mdx
+123-4Lines changed: 123 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -230,10 +230,129 @@ Consequently, a JSX component can cram in a few more props before reaching for e
230
230
231
231
**Note** that this is a departure from ReactJS JSX, which does **not** have punning. ReactJS' `<input checked />` desugars to `<input checked=true />`, in order to conform to DOM's idioms and for backward compatibility.
For library authors wanting to take advantage of the JSX: the `@JSX` attribute is a hook for potential ppx macros to spot a function wanting to format as JSX. Once you spot the function, you can turn it into any other expression.
235
+
**Since 11.1**
236
236
237
-
This way, everyone gets to benefit the JSX syntax without needing to opt into a specific library using it, e.g. ReScriptReact.
237
+
While ReScript comes with first class support for JSX in React, it's also possible to have ReScript delegate JSX to other frameworks. You do that by configuring a _generic JSX transform_.
238
238
239
-
JSX calls supports the features of [labeled arguments](function.md#labeled-arguments): optional, explicitly passed optional and optional with default.
239
+
This is what you need to do to use a generic JSX transform:
240
+
1. Make sure you have a ReScript module that [implements the functions and types necessary for the JSX transform](#implementing-a-generic-jsx-transform-module).
241
+
2. Configure `rescript.json` to delegated JSX to that module.
242
+
243
+
That's it really. We'll expand on each point below.
244
+
245
+
### Configuration
246
+
You configure a generic JSX transform by putting any module name in the `module` config of JSX in `rescript.json`. This can be _any valid module name_. Example part from `rescript.json`:
247
+
248
+
```json
249
+
"jsx": {
250
+
"module": "Preact"
251
+
},
252
+
```
253
+
254
+
This will now put the `Preact` module in control of the generated JSX calls. The `Preact` module can be defined by anyone - locally in your project, or by a package. As long a it's available in the global scope. The JSX transform will delegate any JSX related code to `Preact`.
255
+
256
+
#### What about `@react.component` for components?
257
+
258
+
`@react.component` will still be available, and so is a generic `@jsx.component` notation. Both work the same way.
259
+
260
+
### Usage Example
261
+
Here's a quick usage example (the actual definition of `Preact.res` comes below):
262
+
263
+
First, configure `rescript.json`:
264
+
```json
265
+
"jsx": {
266
+
"module": "Preact"
267
+
},
268
+
```
269
+
270
+
Now you can build Preact components:
271
+
```rescript
272
+
// Name.res
273
+
@jsx.component // or @react.component if you want
274
+
let make = (~name) => Preact.string(`Hello ${name}!`)
275
+
```
276
+
277
+
And you can use them just like normal with JSX:
278
+
```rescript
279
+
let name = <Name name="Test" />
280
+
```
281
+
282
+
#### File level configuration
283
+
You can configure what JSX transform is used at the file level via `@@jsxConfig`, just like before. Like:
284
+
```rescript
285
+
@@jsxConfig({module_: "Preact"})
286
+
```
287
+
288
+
This can be convenient if you're mixing different JSX frameworks in the same project.
289
+
290
+
### Implementing a generic JSX transform module
291
+
Below is a full list of everything you need in a generic JSX transform module, including code comments to clarify. It's an example implementation of a `Preact` transform, so when doing this for other frameworks you'd of course adapt what you import from, and so on.
292
+
293
+
> You can easily copy-paste-and-adapt this to your needs if you're creating bindings to a JSX framework. Most often, all you'll need to change is what the `@module("") external` points to, so the runtime calls point to the correct JS module.
294
+
295
+
```rescript
296
+
// Preact.res
297
+
/* Below is a number of aliases to the common `Jsx` module */
298
+
type element = Jsx.element
299
+
300
+
type component<'props> = Jsx.component<'props>
301
+
302
+
type componentLike<'props, 'return> = Jsx.componentLike<'props, 'return>
303
+
304
+
@module("preact")
305
+
external jsx: (component<'props>, 'props) => element = "jsx"
external someElement: element => option<element> = "%identity"
355
+
}
356
+
```
357
+
358
+
As you can see, most of the things you'll want to implement will be copy paste from the above. But do note that **everything needs to be there unless explicitly noted** or the transform will fail at compile time.
0 commit comments