From 85120f3bf4c948e21005c2ccbd2556477ebbbc63 Mon Sep 17 00:00:00 2001 From: John Haley Date: Thu, 20 Feb 2025 19:42:00 -0700 Subject: [PATCH 1/3] update dependencies to work with opam 2.3 --- dune-project | 6 +++--- reason-react-ppx.opam | 2 +- reason-react.opam | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dune-project b/dune-project index fbeb92d80..886d208cb 100644 --- a/dune-project +++ b/dune-project @@ -43,11 +43,11 @@ (ocaml-lsp-server :with-dev-setup) (opam-check-npm-deps (and - (= 1.0.0) + (= 3.0.1) :with-dev-setup)) (ocamlformat (and - (= 0.24.0) + (= 0.27.0) :with-dev-setup)))) (package @@ -64,5 +64,5 @@ (merlin :with-test) (ocamlformat (and - (= 0.24.0) + (= 0.27.0) :with-dev-setup)))) diff --git a/reason-react-ppx.opam b/reason-react-ppx.opam index e9f168131..8bbc1290c 100644 --- a/reason-react-ppx.opam +++ b/reason-react-ppx.opam @@ -19,7 +19,7 @@ depends: [ "reason" {>= "3.12.0"} "ppxlib" {>= "0.33.0"} "merlin" {with-test} - "ocamlformat" {= "0.24.0" & with-dev-setup} + "ocamlformat" {= "0.27.0" & with-dev-setup} "odoc" {with-doc} ] build: [ diff --git a/reason-react.opam b/reason-react.opam index e2329051c..1a8cc20d6 100644 --- a/reason-react.opam +++ b/reason-react.opam @@ -23,8 +23,8 @@ depends: [ "reason-react-ppx" {= version} "reason" {>= "3.12.0"} "ocaml-lsp-server" {with-dev-setup} - "opam-check-npm-deps" {= "1.0.0" & with-dev-setup} - "ocamlformat" {= "0.24.0" & with-dev-setup} + "opam-check-npm-deps" {= "3.0.1" & with-dev-setup} + "ocamlformat" {= "0.27.0" & with-dev-setup} "odoc" {with-doc} ] build: [ From fb83ec467f9fa0ac41521740e7ec0bc121004ffa Mon Sep 17 00:00:00 2001 From: John Haley Date: Thu, 20 Feb 2025 19:42:39 -0700 Subject: [PATCH 2/3] update `make install` to also install dev deps --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3512619a7..6ffd83c0e 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ format-check: ## Checks if format is correct .PHONY: install install: ## Update the package dependencies when new deps are added to dune-project - @opam install . --deps-only --with-test + @opam install . --deps-only --with-test --with-dev-setup @npm install .PHONY: init From 8b6c2de0f3b32dd7b6d45d06ee638d9c1c2b6107 Mon Sep 17 00:00:00 2001 From: John Haley Date: Thu, 20 Feb 2025 20:48:34 -0700 Subject: [PATCH 3/3] add `list` for rendering lists of elements By adding `React.list` this will allow us to delay converting lists to arrays until the final layer. --- docs/components.md | 3 ++- src/React.re | 1 + src/React.rei | 4 +++- test/React__test.re | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/docs/components.md b/docs/components.md index 2a667aa13..814c046a8 100644 --- a/docs/components.md +++ b/docs/components.md @@ -65,7 +65,7 @@ The component above could be called like this: ``` -## Rendering text, int, floats, arrays and null +## Rendering text, int, floats, arrays, lists, and null In order for the compiler to understand that rendering a string of text or a number is intentional, you need to explicitely write it: @@ -75,6 +75,7 @@ In order for the compiler to understand that rendering a string of text or a num {React.int(3)} {React.float(1.23)} {React.array([|
, |])} + {React.list([
, ])} {React.null}
``` diff --git a/src/React.re b/src/React.re index 17a7f61b1..9c55d8f31 100644 --- a/src/React.re +++ b/src/React.re @@ -309,6 +309,7 @@ external float: float => element = "%identity"; external int: int => element = "%identity"; external string: string => element = "%identity"; external array: array(element) => element = "%identity"; +let list: list(element) => element = xs => xs |> Array.of_list |> array; /* this function exists to prepare for making `component` abstract */ external component: componentLike('props, element) => component('props) = diff --git a/src/React.rei b/src/React.rei index c7664b2ba..27bb710ad 100644 --- a/src/React.rei +++ b/src/React.rei @@ -7,6 +7,7 @@ external float: float => element = "%identity"; external int: int => element = "%identity"; external string: string => element = "%identity"; external array: array(element) => element = "%identity"; +let list: list(element) => element; /* this function exists to prepare for making `component` abstract */ external component: componentLike('props, element) => component('props) = @@ -565,7 +566,8 @@ module Uncurried: { }; [@mel.module "react"] -external startTransition: ([@mel.uncurry] (unit => unit)) => unit = "startTransition"; +external startTransition: ([@mel.uncurry] (unit => unit)) => unit = + "startTransition"; [@mel.module "react"] external useTransition: unit => (bool, callback(callback(unit, unit), unit)) = diff --git a/test/React__test.re b/test/React__test.re index 4bb4d9158..b9584cd9d 100644 --- a/test/React__test.re +++ b/test/React__test.re @@ -169,6 +169,39 @@ describe("React", () => { ->toBe(true); }); + test("can render list of elements", () => { + let container = getContainer(container); + let list = + [1, 2, 3] + ->List.map(item => { +
item->React.int
+ }); + let root = ReactDOM.Client.createRoot(container); + + act(() => {ReactDOM.Client.render(root,
list->React.list
)}); + + expect( + container + ->DOM.findBySelectorAndPartialTextContent("div", "1") + ->Option.isSome, + ) + ->toBe(true); + + expect( + container + ->DOM.findBySelectorAndPartialTextContent("div", "2") + ->Option.isSome, + ) + ->toBe(true); + + expect( + container + ->DOM.findBySelectorAndPartialTextContent("div", "3") + ->Option.isSome, + ) + ->toBe(true); + }); + test("can clone an element", () => { let container = getContainer(container); let root = ReactDOM.Client.createRoot(container);