From 7a5f5eb9cf4e3e0cfb0cc0e2f80e5fa372e37e94 Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Tue, 3 Jun 2025 15:47:28 +0200 Subject: [PATCH 1/9] Add unreleased PRs into CHANGES.md --- CHANGES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 5422e0508..bb3f79a25 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,14 @@ # Unreleased +* FEATURE: add color to domProps (@tatchy in https://github.com/reasonml/reason-react/pull/871) +* BREAKING: Support for React 19 (@davesnx in #846) +* DOCS: Documentation updates for 0.16 (@davesnx in https://github.com/reasonml/reason-react/pull/864) +* INFRA: Update deps (@johnhaley81 in https://github.com/reasonml/reason-react/pull/876) +* INFRA: update setup-ocaml to v3 (@anmonteiro in https://github.com/reasonml/reason-react/pull/878) +* FIX: Remove raise annotations and fix locations on errors (@davesnx https://github.com/reasonml/reason-react/pull/863) +* FIX: type of pipeable stream to allow objects with keys (@anmonteiro in https://github.com/reasonml/reason-react/pull/854) +* FEATURE: Add `preconnect`, `prefetchDNS`, `preinit`, `preinitModule`, `preload` and `preloadModule` in ReactDOM.Experimental (@r17x in https://github.com/reasonml/reason-react/pull/849) + # 0.15.0 * Add `isValidElement` (@r17x in From 4864f43313c4fba65663bd04312ca3bfefd6d047 Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Tue, 3 Jun 2025 15:47:49 +0200 Subject: [PATCH 2/9] Update @testing-library/react to latest with React 19 --- package-lock.json | 21 ++++++++++----------- package.json | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) 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..0a6372a49 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,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", From cfd419814a7a47738d54253ba481103ab9c19cbf Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Tue, 3 Jun 2025 15:48:49 +0200 Subject: [PATCH 3/9] Remove version and metadata on package.json --- package.json | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 0a6372a49..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": { From 6bb1ac693d086dd9573959549f80d7c3f3ee6f5b Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Tue, 3 Jun 2025 16:04:33 +0200 Subject: [PATCH 4/9] Fix melange dep in dune-project, from 5cd06608c08893f5f39e529e337b2e6eef3119a9 --- dune-project | 8 ++------ reason-react.opam | 3 ++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/dune-project b/dune-project index 3d63322e5..98b0a95fa 100644 --- a/dune-project +++ b/dune-project @@ -34,12 +34,8 @@ "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.") (depends ocaml - (melange - (or - (>= 3.0.0) - (and - (= 5.0.0-52) - :with-test))) + (melange (>= 3.0.0)) + (melange (and (= 5.0.0-52) :with-test)) (reason-react-ppx (= :version)) (reason diff --git a/reason-react.opam b/reason-react.opam index fd981b503..c7b0c6d55 100644 --- a/reason-react.opam +++ b/reason-react.opam @@ -19,7 +19,8 @@ bug-reports: "https://github.com/reasonml/reason-react/issues" depends: [ "dune" {>= "3.9"} "ocaml" - "melange" {(>= "3.0.0" & !with-test) | (= "5.0.0-52" & with-test)} + "melange" {>= "3.0.0"} + "melange" {= "5.0.0-52" & with-test} "reason-react-ppx" {= version} "reason" {>= "3.12.0"} "ocaml-lsp-server" {with-dev-setup} From 09a6b697a41d01dafe7bab4b0409ca06348db68e Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Tue, 3 Jun 2025 17:07:27 +0200 Subject: [PATCH 5/9] Rename ReasonReact to reason-react --- dune-project | 4 ++-- reason-react-ppx.opam | 2 +- reason-react.opam | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dune-project b/dune-project index 98b0a95fa..0bea373be 100644 --- a/dune-project +++ b/dune-project @@ -31,7 +31,7 @@ (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 (>= 3.0.0)) @@ -53,7 +53,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/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 c7b0c6d55..28eff6fbc 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: [ From 856b5a53d3dcc05663038c902a94279f2ad2ef8c Mon Sep 17 00:00:00 2001 From: David Sancho Date: Wed, 4 Jun 2025 12:38:09 +0200 Subject: [PATCH 6/9] Review most React 19's API (#894) * Rename ReasonReact to reason-react * Add initialValue into useDeferredValue * Add useTransitionAsync * Add Experimental.promise * Add initialValue into useDeferredValue in React.rei * Explain new (2020) jsx transformation (#896) --- docs/jsx.md | 68 +++++++++++++++++++++++++------------------ dune-project | 4 +-- reason-react-ppx.opam | 2 +- reason-react.opam | 2 +- src/React.re | 12 +++++++- src/React.rei | 12 +++++++- 6 files changed, 66 insertions(+), 34 deletions(-) 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 98b0a95fa..0bea373be 100644 --- a/dune-project +++ b/dune-project @@ -31,7 +31,7 @@ (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 (>= 3.0.0)) @@ -53,7 +53,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/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 c7b0c6d55..28eff6fbc 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: [ diff --git a/src/React.re b/src/React.re index ae8cd326e..289044551 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 a2bcefb0e..29e5c63f5 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"; From c29fc07729d5615b072f96e958df7d0043676c45 Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Wed, 4 Jun 2025 12:42:07 +0200 Subject: [PATCH 7/9] Add 5.1.0 as lower bound --- CHANGES.md | 1 + dune-project | 3 +-- reason-react.opam | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bb3f79a25..421735801 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ * FIX: Remove raise annotations and fix locations on errors (@davesnx https://github.com/reasonml/reason-react/pull/863) * FIX: type of pipeable stream to allow objects with keys (@anmonteiro in https://github.com/reasonml/reason-react/pull/854) * FEATURE: Add `preconnect`, `prefetchDNS`, `preinit`, `preinitModule`, `preload` and `preloadModule` in ReactDOM.Experimental (@r17x in https://github.com/reasonml/reason-react/pull/849) +* BREAKING: Make lowerbound be Melange 5.1 (due to Js.FormData.t usage) # 0.15.0 diff --git a/dune-project b/dune-project index 0bea373be..0c7560ffe 100644 --- a/dune-project +++ b/dune-project @@ -34,8 +34,7 @@ "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 (>= 3.0.0)) - (melange (and (= 5.0.0-52) :with-test)) + (melange (<= 5.1.0)) (reason-react-ppx (= :version)) (reason diff --git a/reason-react.opam b/reason-react.opam index 28eff6fbc..08cc1aac3 100644 --- a/reason-react.opam +++ b/reason-react.opam @@ -19,8 +19,7 @@ bug-reports: "https://github.com/reasonml/reason-react/issues" depends: [ "dune" {>= "3.9"} "ocaml" - "melange" {>= "3.0.0"} - "melange" {= "5.0.0-52" & with-test} + "melange" {<= "5.1.0"} "reason-react-ppx" {= version} "reason" {>= "3.12.0"} "ocaml-lsp-server" {with-dev-setup} From e307742a01015ad7471825da470d36810183164c Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Wed, 4 Jun 2025 14:49:08 +0200 Subject: [PATCH 8/9] Update opam-check-npm-deps react, react-dom to 19.1.0 --- reason-react.opam | 4 ++-- reason-react.opam.template | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/reason-react.opam b/reason-react.opam index 08cc1aac3..44b9a1a3e 100644 --- a/reason-react.opam +++ b/reason-react.opam @@ -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"} ] From 0c162046508ff48bb09df2e1b9e47a7af3283b62 Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Fri, 13 Jun 2025 15:40:09 +0200 Subject: [PATCH 9/9] Add ?dev in demo, and add example for fragments --- demo/index.html | 8 +++---- demo/main.re | 56 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/demo/index.html b/demo/index.html index e333157fd..c65734377 100644 --- a/demo/index.html +++ b/demo/index.html @@ -25,10 +25,10 @@ "melange.belt/": "./demo/node_modules/melange.belt/", "melange.js/": "./demo/node_modules/melange.js/", "reason-react/": "./demo/node_modules/reason-react/", - "react/jsx-runtime": "https://esm.sh/react@19.0.0-rc.1/jsx-runtime", - "react": "https://esm.sh/react@19.0.0-rc.1", - "react-dom": "https://esm.sh/react-dom@19.0.0-rc.1", - "react-dom/client": "https://esm.sh/react-dom@19.0.0-rc.1/client" + "react/jsx-runtime": "https://esm.sh/react@19.1.0/jsx-runtime?dev", + "react": "https://esm.sh/react@19.1.0?dev", + "react-dom": "https://esm.sh/react-dom@19.1.0?dev", + "react-dom/client": "https://esm.sh/react-dom@19.1.0/client?dev" } } diff --git a/demo/main.re b/demo/main.re index 8994a58dc..c76c63272 100644 --- a/demo/main.re +++ b/demo/main.re @@ -161,6 +161,59 @@ module UseReducerNoProblemo = { }; }; +module FragmentsEverywhere = { + [@react.component] + let make = () => { + let items = ["Apple", "Banana", "Cherry", "Date"]; + let numbers = [1, 2, 3, 4, 5]; + +
+

{React.string("Fragments Everywhere")}

+ +

{React.string("This is inside a fragment")}

+ {React.string("Multiple elements together")} + {React.string("Without a wrapper div")} +
+
+

{React.string("List of items with fragments:")}

+ {items + |> List.mapi((index, item) => + + {React.string(item)} + + {React.string(" - Item #" ++ string_of_int(index + 1))} + +
+
+ ) + |> Array.of_list + |> React.array} +
+ <> +
+

{React.string("Another fragment section")}

+ + {React.string("Emphasized text")} + +
+

{React.string("Numbers with fragments:")}

+ {numbers + |> List.mapi((index, num) => + +
{React.string("Number: " ++ string_of_int(num))}
+ + {React.string("Square: " ++ string_of_int(num * num))} + +
+
+ ) + |> Array.of_list + |> React.array} +
+
; + }; +}; + module App = { [@react.component] let make = (~initialValue) => { @@ -174,7 +227,8 @@ module App = { - + + ; }; };