+ ;
+ };
+};
+
+module WithoutForward = {
+ [@react.component]
+ let make = (~ref=?) => {
+ ;
+ };
+};
+
module App = {
[@react.component]
let make = (~initialValue) => {
@@ -174,7 +234,9 @@ module App = {
-
+
+
+
;
};
};
diff --git a/docs/jsx.md b/docs/jsx.md
index caf80474a..e562c91fc 100644
--- a/docs/jsx.md
+++ b/docs/jsx.md
@@ -2,11 +2,19 @@
title: JSX
---
-Reason comes with the [JSX](https://reasonml.github.io/docs/en/jsx.html) syntax! ReasonReact works very similar to how [the ReactJS JSX transform](https://reactjs.org/docs/introducing-jsx.html) does.
+Reason comes with [JSX](https://reasonml.github.io/docs/en/jsx.html) syntax. Enables representation of HTML-like expressions within the language.
+
+reason-react enables [the ReactJS JSX transform](https://reactjs.org/docs/introducing-jsx.html) in Reason.
+
+Since `reason-react.0.12.0`, the JSX transformation currently supports the [New JSX Transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html). JSX functions are imported from `react/jsx-runtime`. Previous versions of reason-react used the legacy API `React.createElement`.
+
+# Install
To use it, you would need to install [`reason-react-ppx`](https://opam.ocaml.org/packages/reason-react-ppx/) and add `(preprocess (pps reason-react-ppx))` in [`melange.emit or library`](https://dune.readthedocs.io/en/stable/melange.html) stanzas in your `dune` file.
-Here's a list of transformations made by the [ppx](https://ocaml.org/docs/metaprogramming):
+# What the ppx does
+
+Here's a list of transformations made by the [ppx](https://ocaml.org/docs/metaprogramming).
## Uncapitalized
@@ -17,27 +25,26 @@ Here's a list of transformations made by the [ppx](https://ocaml.org/docs/metapr
transforms into
```reason
-ReactDOM.createDOMElementVariadic(
+ReactDOM.jsxs(
"div",
- ~props=ReactDOM.domProps(~foo=bar, ()),
- [|child1, child2|]
-);
+ ReactDOM.domProps(
+ ~children=React.array([|child1, child2|]),
+ ~foo=bar,
+ (),
+ )
+)
```
which compiles to the JavaScript code:
```js
-React.createElement('div', {foo: bar}, child1, child2)
+React.jsx('div', {foo: bar, children: [ child1, child2 ] })
```
Prop-less `
` transforms into
```reason
-ReactDOM.createDOMElementVariadic(
- "div",
- ~props=ReactDOM.domProps(),
- [||]
-);
+ReactDOM.jsx("div", ReactDOM.domProps());
```
Which compiles to
@@ -49,61 +56,63 @@ React.createElement('div', {})
## Capitalized
```reason
- {child1} {child2}
+ {child1} {child2}
```
transforms into
```reason
-React.createElementVariadic(
+React.jsxs(
MyReasonComponent.make,
MyReasonComponent.makeProps(
- ~key=a,
~ref=b,
~foo=bar,
~baz=qux,
- ~children=React.null,
+ ~children=[|child1, child2|],
()
),
- [|child1, child2|]
);
```
which compiles to
```js
-React.createElement(
+React.jsxs(
MyReasonComponent.make,
{
- key: a,
ref: b,
foo: bar,
baz: qux,
- children: null,
+ children: [ child1, child2 ],
},
- child1,
- child2,
);
```
Prop-less `` transforms into
```reason
-React.createElement(MyReasonComponent.make, MyReasonComponent.makeProps());
+React.jsx(
+ MyReasonComponent.make,
+ MyReasonComponent.makeProps(),
+);
```
which compiles to
```js
-React.createElement(MyReasonComponent.make, {});
+React.jsx(MyReasonComponent.make, {});
```
The `make` above is exactly the same `make` function you've seen in the previous section.
-`ref` and `key` are reserved in ReasonReact, just like in ReactJS. **Don't** use them as props in your component!
+`ref` and `key` are reserved in reason-react, just like in ReactJS. **Don't** use them as props in your component!
## Fragment
+Fragment lets you group elements without a wrapper node, and return a single element without any effect on the DOM. More details about this in the [react documentation: Fragments](https://react.dev/reference/react/Fragment).
+
+The empty JSX tag `<>>` is shorthand for ``
+
```reason
<> child1 child2 >;
```
@@ -111,18 +120,21 @@ The `make` above is exactly the same `make` function you've seen in the previous
transforms into
```reason
-ReactDOMRe.createElement(ReasonReact.fragment, [|child1, child2|]);
+React.jsx(
+ React.jsxFragment,
+ ReactDOM.domProps(~children=React.array([|child1, child2|]), ()),
+);
```
Which compiles to
```js
-React.createElement(React.Fragment, undefined, child1, child2);
+React.jsx(React.Fragment, { children: [child1, child2] });
```
## Children
-ReasonReact children are **fully typed**, and you can pass any data structure to it (as long as the receiver component permits it). When you write:
+reason-react children are **fully typed**, and you can pass any data structure to it (as long as the receiver component permits it). When you write:
```reason
diff --git a/dune-project b/dune-project
index 29e6af47d..0c7560ffe 100644
--- a/dune-project
+++ b/dune-project
@@ -31,15 +31,10 @@
(name reason-react)
(synopsis "Reason bindings for React.js")
(description
- "ReasonReact helps you use Reason to build React components with deeply integrated, strong, static type safety.\n\nIt is designed and built by people using Reason and React in large, mission critical production React codebases.")
+ "reason-react helps you use Reason to build React components with deeply integrated, strong, static type safety.\n\nIt is designed and built by people using Reason and React in large, mission critical production React codebases.")
(depends
ocaml
- (melange
- (or
- (>= 3.0.0)
- (and
- (<= 5.1.0-53)
- :with-test)))
+ (melange (<= 5.1.0))
(reason-react-ppx
(= :version))
(reason
@@ -57,7 +52,7 @@
(package
(name reason-react-ppx)
(synopsis "React.js JSX PPX")
- (description "ReasonReact JSX PPX")
+ (description "reason-react JSX PPX")
(depends
(ocaml
(>= 4.14))
diff --git a/package-lock.json b/package-lock.json
index dc6c72fd2..8917e8778 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,16 +1,16 @@
{
"name": "reason-react",
- "version": "0.11.0",
+ "version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "reason-react",
- "version": "0.11.0",
+ "version": "0.0.0",
"license": "MIT",
"devDependencies": {
"@testing-library/dom": "^10.4.0",
- "@testing-library/react": "^16.0.1",
+ "@testing-library/react": "^16.3.0",
"http-server": "^14.1.1",
"jest": "^26.0.1",
"react": "^19.1.0",
@@ -1018,11 +1018,10 @@
}
},
"node_modules/@testing-library/react": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz",
- "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz",
+ "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5"
},
@@ -1031,10 +1030,10 @@
},
"peerDependencies": {
"@testing-library/dom": "^10.0.0",
- "@types/react": "^18.0.0",
- "@types/react-dom": "^18.0.0",
- "react": "^18.0.0",
- "react-dom": "^18.0.0"
+ "@types/react": "^18.0.0 || ^19.0.0",
+ "@types/react-dom": "^18.0.0 || ^19.0.0",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
diff --git a/package.json b/package.json
index 1389098f1..b22df63ec 100644
--- a/package.json
+++ b/package.json
@@ -1,22 +1,7 @@
{
"name": "reason-react",
- "version": "0.11.0",
- "description": "React bindings for Reason",
- "files": [
- "dune",
- "dune-project",
- "README.md",
- "HISTORY.md",
- "LICENSE",
- "src",
- "ppx/src",
- "reason-react-ppx.opam",
- "reason-react.opam"
- ],
- "keywords": [
- "reasonml",
- "react"
- ],
+ "version": "0.0.0",
+ "description": "This package.json is used to install node development dependencies",
"author": "",
"license": "MIT",
"repository": {
@@ -26,7 +11,7 @@
"homepage": "https://reasonml.github.io/reason-react/",
"devDependencies": {
"@testing-library/dom": "^10.4.0",
- "@testing-library/react": "^16.0.1",
+ "@testing-library/react": "^16.3.0",
"http-server": "^14.1.1",
"jest": "^26.0.1",
"react": "^19.1.0",
diff --git a/reason-react-ppx.opam b/reason-react-ppx.opam
index 8bbc1290c..b827c1ed0 100644
--- a/reason-react-ppx.opam
+++ b/reason-react-ppx.opam
@@ -1,7 +1,7 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "React.js JSX PPX"
-description: "ReasonReact JSX PPX"
+description: "reason-react JSX PPX"
maintainer: [
"David Sancho "
"Antonio Monteiro "
diff --git a/reason-react.opam b/reason-react.opam
index 46fc4897c..44b9a1a3e 100644
--- a/reason-react.opam
+++ b/reason-react.opam
@@ -2,7 +2,7 @@
opam-version: "2.0"
synopsis: "Reason bindings for React.js"
description: """
-ReasonReact helps you use Reason to build React components with deeply integrated, strong, static type safety.
+reason-react helps you use Reason to build React components with deeply integrated, strong, static type safety.
It is designed and built by people using Reason and React in large, mission critical production React codebases."""
maintainer: [
@@ -19,7 +19,7 @@ bug-reports: "https://github.com/reasonml/reason-react/issues"
depends: [
"dune" {>= "3.9"}
"ocaml"
- "melange" {>= "3.0.0" | <= "5.1.0-53" & with-test}
+ "melange" {<= "5.1.0"}
"reason-react-ppx" {= version}
"reason" {>= "3.12.0"}
"ocaml-lsp-server" {with-dev-setup}
@@ -43,6 +43,6 @@ build: [
]
dev-repo: "git+https://github.com/reasonml/reason-react.git"
depexts: [
- ["react"] {npm-version = "^18.0.0"}
- ["react-dom"] {npm-version = "^18.0.0"}
+ ["react"] {npm-version = "^19.1.0"}
+ ["react-dom"] {npm-version = "^19.1.0"}
]
diff --git a/reason-react.opam.template b/reason-react.opam.template
index d287dfa45..71bb69881 100644
--- a/reason-react.opam.template
+++ b/reason-react.opam.template
@@ -1,4 +1,4 @@
depexts: [
- ["react"] {npm-version = "^18.0.0"}
- ["react-dom"] {npm-version = "^18.0.0"}
+ ["react"] {npm-version = "^19.1.0"}
+ ["react-dom"] {npm-version = "^19.1.0"}
]
diff --git a/src/React.re b/src/React.re
index 77c7e1705..b0fe5d81b 100644
--- a/src/React.re
+++ b/src/React.re
@@ -723,7 +723,9 @@ external useContext: Context.t('any) => 'any = "useContext";
[@mel.module "react"] external useRef: 'value => ref('value) = "useRef";
[@mel.module "react"] external useId: unit => string = "useId";
-[@mel.module "react"] external useDeferredValue: 'a => 'a = "useDeferredValue";
+[@mel.module "react"]
+external useDeferredValue: ('a, ~initialValue: 'a=?) => 'a =
+ "useDeferredValue";
[@mel.module "react"]
external useImperativeHandle0:
@@ -877,6 +879,11 @@ module Uncurried = {
external useTransition: unit => (bool, callback(callback(unit, unit), unit)) =
"useTransition";
+[@mel.module "react"]
+external useTransitionAsync:
+ unit => (bool, callbackAsync(callback(unit, unit), unit)) =
+ "useTransition";
+
[@mel.module "react"]
external startTransition: ([@mel.uncurry] (unit => unit)) => unit =
"startTransition";
@@ -887,12 +894,15 @@ external useDebugValue: ('value, ~format: 'value => string=?, unit) => unit =
[@mel.module "react"]
external act: (unit => unit) => Js.Promise.t(unit) = "act";
+
[@mel.module "react"]
external actAsync: (unit => Js.Promise.t(unit)) => Js.Promise.t(unit) =
"act";
module Experimental = {
/* This module is used to bind to APIs for future versions of React. There is no guarantee of backwards compatibility or stability. */
+ external promise: Js.Promise.t(element) => element = "%identity";
+
/* https://react.dev/reference/react/use */
[@mel.module "react"] external usePromise: Js.Promise.t('a) => 'a = "use";
[@mel.module "react"] external useContext: Context.t('a) => 'a = "use";
diff --git a/src/React.rei b/src/React.rei
index 367ccdf18..dee162e1a 100644
--- a/src/React.rei
+++ b/src/React.rei
@@ -415,7 +415,9 @@ external useContext: Context.t('any) => 'any = "useContext";
[@mel.module "react"] external useRef: 'value => ref('value) = "useRef";
[@mel.module "react"] external useId: unit => string = "useId";
-[@mel.module "react"] external useDeferredValue: 'a => 'a = "useDeferredValue";
+[@mel.module "react"]
+external useDeferredValue: ('a, ~initialValue: 'a=?) => 'a =
+ "useDeferredValue";
[@mel.module "react"]
external useImperativeHandle0:
@@ -573,14 +575,22 @@ external startTransition: ([@mel.uncurry] (unit => unit)) => unit =
external useTransition: unit => (bool, callback(callback(unit, unit), unit)) =
"useTransition";
+[@mel.module "react"]
+external useTransitionAsync:
+ unit => (bool, callbackAsync(callback(unit, unit), unit)) =
+ "useTransition";
+
[@mel.module "react"]
external act: (unit => unit) => Js.Promise.t(unit) = "act";
+
[@mel.module "react"]
external actAsync: (unit => Js.Promise.t(unit)) => Js.Promise.t(unit) =
"act";
module Experimental: {
/* This module is used to bind to APIs for future versions of React. There is no guarantee of backwards compatibility or stability. */
+ external promise: Js.Promise.t(element) => element = "%identity";
+
[@mel.module "react"] external usePromise: Js.Promise.t('a) => 'a = "use";
[@mel.module "react"] external useContext: Context.t('a) => 'a = "use";
diff --git a/src/ReactDOM.rei b/src/ReactDOM.rei
index ed35c948d..75de82b44 100644
--- a/src/ReactDOM.rei
+++ b/src/ReactDOM.rei
@@ -472,6 +472,9 @@ external createPortal: (React.element, Dom.element) => React.element =
"createPortal";
[@mel.module "react-dom"]
+[@deprecated
+ "Use ReactDOM.Client.unmount instead. This function will be removed in the next release."
+]
external unmountComponentAtNode: Dom.element => unit =
"unmountComponentAtNode";