# Jsoo approach to react / gui

**URL:** <https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382>\
**Category:** Learning\
**Created:** [February 9, 2023, 10:00pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382 "2023-02-09T22:00:32Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zeroexcuses/32/1692_2.png) [@zeroexcuses](https://discuss.ocaml.org/u/zeroexcuses)\
**Post date:** [February 9, 2023, 10:00pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/1 "2023-02-09T22:00:33Z")

</div>

What is the jsoo approach to React ?

For example, JS/TS have builtin “syntax support” via JS → JSX, TS → TSX.

For jsoo, what is the approach to building GUI components ?

1. jsoo with react, no syntax
2. jsoo with react, special syntax (how do we extend?)
3. jsoo without react (what library do we use? incr / functional-relational-programming related libs?)

---

<div class="post-metadata">

**Author:** ![zbaylin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zbaylin/32/4047_2.png) [@zbaylin](https://discuss.ocaml.org/u/zbaylin)\
**Post date:** [February 9, 2023, 10:16pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/2 "2023-02-09T22:16:25Z")

</div>

There’s a set of React bindings to JSOO written by @davesnx and @jchavarri, which you can find here: [GitHub - ml-in-barcelona/jsoo-react: js\_of\_ocaml bindings for ReactJS. Based on ReasonReact.](https://github.com/ml-in-barcelona/jsoo-react)

The library includes a ppx which transforms the syntax _slightly_, but it doesn’t give you JSX or anything like that.

Here’s an example of how a component is written with the DSL + the PPX: [jsoo-react-realworld-example-app/header.ml at main · jchavarri/jsoo-react-realworld-example-app · GitHub](https://github.com/jchavarri/jsoo-react-realworld-example-app/blob/main/src/header.ml)

(that repo broadly is an attempt to port the ReScript example app to jsoo-react. Not sure how completed it is, though)

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [February 9, 2023, 10:26pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/3 "2023-02-09T22:26:31Z")

</div>

You might find these previous threads interesting:

> [@Jsoo, production use and user facing applications questions](https://discuss.ocaml.org/t/jsoo-production-use-and-user-facing-applications-questions/7266/7):
>
> summarizing findings: js\_of\_ocaml deals with just that - generating js of ocaml; javascript imports and interop is possible through creating bindings to js code you can still pass the output of jsoo to the standard javascript build pipelines (including webpack), for example: [Create bindings for JS library · Issue #718 · ocsigen/js\_of\_ocaml · GitHub](https://github.com/ocsigen/js_of_ocaml/issues/718#issuecomment-702587512) I couldn’t find any more complete and more complex examples like using css modules or internationalization, that require “coordination” between b…

> [@Compiling Bonsai](https://discuss.ocaml.org/t/compiling-bonsai/7107):
>
> Hi all, I’d like to try [Bonsai](https://github.com/janestreet/bonsai) to develop a web frontend, since I gave up hope of using Reason and related ecosystem. The version present in opam (v0.14.0) has no examples, while the master on GitHub seems much more complete in that sense but I failed to compile the library because it relies on library not present in opam or versions not released yet. So I created a new switch and pinned all the relevant dev-repo but still no success. For example I can’t find any “1.0.6+newsyntax” version of [g…](https://github.com/LexiFi/gen_js_api)

> [@Tutorial: Full-Stack Web Dev in OCaml w/ Dream, Bonsai, and GraphQL](https://discuss.ocaml.org/t/tutorial-full-stack-web-dev-in-ocaml-w-dream-bonsai-and-graphql/9963):
>
> Hi everyone! I’ve written a tutorial blog series about full-stack web development in OCaml, and wanted to share it here. Last semester, I took Penn State’s [CMPSC 431W](https://bulletins.psu.edu/university-course-descriptions/undergraduate/cmpsc/#:~:text=CMPSC%20431W%3A%20Database%20Management%20Systems), where our final project was to build a database-driven web application. Since I’m fairly familiar with web programming through my work on [Flarum](https://flarum.org/) and past internships/side projects, I decided to use this opportunity to explore the OCaml web development ecosystem. I used [Dream](https://aantron.github.io/dream/) for the backend, and [Bonsai](https://github.com/janestreet/bonsai) for the frontend. While wo…

---

<div class="post-metadata">

**Author:** ![davesnx](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/davesnx/32/2949_2.png) [@davesnx](https://discuss.ocaml.org/u/davesnx)\
**Post date:** [February 9, 2023, 10:41pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/4 "2023-02-09T22:41:19Z")

</div>

Thanks for the mention @zbaylin.

We made jsoo-react with OCaml syntax in mind, but If you look for JSX, the inmediate solution is to go for Reason (and keep the components in Reason syntax)

---

<div class="post-metadata">

**Author:** ![bhoot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bhoot/32/5900_2.png) [@bhoot](https://discuss.ocaml.org/u/bhoot)\
**Post date:** [February 10, 2023, 3:35am UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/5 "2023-02-10T03:35:19Z")

</div>

I am only here to worsen your dilemma.

Like me, you may feel less frustrated by not using JSOO barebones. Instead, use either Brr or gen\_js\_api bindings to JSOO.

Coupling that with the libraries that use The Elm Architecture (TEA), which had also inspired React (and is a much more complete concept than React is), there are quite a few paths for you:

Based on JSOO:

- jsoo + gen\_js\_api + ocaml-vdom (TEA)
- “jsoo + Brr + Note (which uses FRP instead of TEA or React’s philosophy)”
- jsoo + gen\_js\_api + jsoo-react
- jsoo + (incr\_dom or bonsai)

I found the documentation and usage of Brr much simpler than those of gen\_js\_api. @dbuenzli clarifies what Brr is further down in this thread.

Not based on JSOO

- melange + bucklescript-tea
- melange + reason-react(?)
- melange + bindings to whichever JS library you can fathom

---

<div class="post-metadata">

**Author:** ![haochenx](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/haochenx/32/4625_2.png) [@haochenx](https://discuss.ocaml.org/u/haochenx)\
**Post date:** [February 10, 2023, 1:05pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/6 "2023-02-10T13:05:26Z")

</div>

Putting my two cents: I was able to achieve satisfactory developer experience using react in pure ML syntax in a toy project. Although the experiment used the ML syntax of ReScript instead of JSOO, you should be able to achieve the same result with a bit of extra works regarding FFI.

I built simple wrapper functions around react element constructors (“function components” in react jargons) mapping properties to labeled arguments and children to the only positional argument as a list (except those elements that never take children, e.g. `<br/>`, which take a single unit as the positional argument). This approach would allow you to build the virtual DOM in the following way:

```ocaml
(** e.g. [address_display ["Pine St. 12"; "ABC Bld."]] would render an equivalent of
    [<div style="font-size: 12">
       <span>Address</span><br/>
       <span key="line-0">Pine St. 12</span><br/>
       <span key="line-1">ABC Bld.</span><br/>
     </div>] *)
let address_display ?(font_size=12) lines =
  div ~style:S.["fontSize", font_size] ([
     span [text_node "Address:"];
     br();
   ] @ lines |> List.mapi (fun i line ->
        fragment [
          span ~key:(sprintf "line-%d" i) [text_node line]);
          br();
        ]
  )

```

which I actually liked better than TSX/JSX.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [February 10, 2023, 10:05pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/7 "2023-02-10T22:05:50Z")

</div>

> [@bhoot](#):
>
> Based on JSOO:
> 
> - jsoo + gen\_js\_api + ocaml-vdom (TEA)
> - jsoo + Brr (which does not use TEA though) + Note
> - jsoo + gen\_js\_api + jsoo-react
> - jsoo + (incr\_dom or bonsai)

This was likely not your intent but I’d just like to mention that this seem a bit to imply exclusive use of these components.

So I’d just mention that [`Brr`](https://erratique.ch/software/brr) is simply bindings to a [selection](https://erratique.ch/software/brr/doc/index#supported_apis) of browser APIs (the `Note` stuff in there is accidental and will migrate elsewhere at some point, likely as an `depopt` of `Note`).

[`gen_js_api`](https://github.com/LexiFi/gen_js_api) is a library to generate bindings to JavaScript libraries.

Both can be used in the same project, including one that uses `incr_dom`, `bonsai` or `ocaml-vdom`.

---

<div class="post-metadata">

**Author:** ![bhoot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bhoot/32/5900_2.png) [@bhoot](https://discuss.ocaml.org/u/bhoot)\
**Post date:** [February 11, 2023, 3:54am UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/8 "2023-02-11T03:54:09Z")

</div>

> This was likely not your intent but I’d just like to mention that this seem a bit to imply exclusive use of these components.

True. I tailored my answer to what the OP asked for.

I bungled the following:

> jsoo + Brr (which does not use TEA though) + Note

What I meant was:

“jsoo + Brr + Note (which does not use TEA or React philosophy)”

* * *

> [`gen_js_api`](https://github.com/LexiFi/gen_js_api) is a library to generate bindings to JavaScript libraries.

Doesn’t the Brr FFI provide a similar capability? Probably through a more manual effort though.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [February 11, 2023, 10:08pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/9 "2023-02-11T22:08:01Z")

</div>

> [@bhoot](#):
>
> Doesn’t the Brr FFI provide a similar capability? Probably through a more manual effort though.

`gen_js_api` generates bindings based on annoted `.mli` files. `Brr` does not generate bindings it provides an [FFI API](https://erratique.ch/software/brr/doc/ffi_manual) built on top of the bare-bone `js_of_ocaml` [one](https://ocsigen.org/js_of_ocaml/latest/api/js_of_ocaml-compiler/Jsoo_runtime/Js/index.html).

Personally I’m not very fond of the `gen_js_api` approach. You need to learn a new language (the annotations), understand how that language translates to FFI calls and then there’s always stuff that escapes the provided patterns, so you may end up fighting with square pegs and round holes (e.g. to express the kind of horrible bureaucracy you find in the [constrainable pattern](https://github.com/dbuenzli/brr/blob/9540f82cf1139968dcb5067a726541ced5f31286/src/brr_io.mli#L971-L978))

Creating bindings with Brr entails a bit more manual work but in the end it’s more flexible to express your binding API and for the programmer it’s just a new OCaml API to learn.

In my experience what took (a lot of) time (and absinthe) was not writing the bindings per se but rather researching, presenting and documenting the JavaScript APIs so that they are enjoyable and productive to use in OCaml.

---

<div class="post-metadata">

**Author:** ![bhoot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bhoot/32/5900_2.png) [@bhoot](https://discuss.ocaml.org/u/bhoot)\
**Post date:** [February 20, 2023, 4:01am UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/10 "2023-02-20T04:01:17Z")

</div>

> the `Note` stuff in there is accidental and will migrate elsewhere at some point, likely as an `depopt` of `Note`

Elm before 0.17 revolved around FRP and signals. [news/farewell-to-frp](https://elm-lang.org/news/farewell-to-frp)

A few (relatively) recent JavaScript libraries like SolidJS also are based on signals (= values that change over time). [https://www.solidjs.com/tutorial/introduction\_signals](https://www.solidjs.com/tutorial/introduction_signals)

I have yet to explore, but in case you already know it, are these similar to Note in philosophy?

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [February 20, 2023, 10:15pm UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/11 "2023-02-20T22:15:31Z")

</div>

Note is an implementation of FRP yes.

I don’t exactly know what these recent JavaScript libraries do, but after all these years I’m glad they are finally discovering [flapjax](https://www.flapjax-lang.org/) :–)

---

<div class="post-metadata">

**Author:** ![benjamin-thomas](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/benjamin-thomas/32/3966_2.png) [@benjamin-thomas](https://discuss.ocaml.org/u/benjamin-thomas)\
**Post date:** [February 21, 2023, 7:02am UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/12 "2023-02-21T07:02:31Z")

</div>

For the sake of discussion, I’ll point out that Angular has FRP “baked in” via the included rxjs library, see this link: [Angular](https://angular.io/guide/rx-library)

@bhoot, the SolidJS intro you linked to looks very similar to Angular idioms.

It’s an interesting concept, however I wasn’t really satisfied with this paradigm (as is applied in Angular), mainly because one can introduce very subtle and hard to debug bugs, quite easily.

Here’s a minimal example demonstrating a “reactive” data flow. Hopefully it should be self explanatory.

```auto
// example.component.ts
import {Component, OnDestroy} from "@angular/core";
import {FormControl, FormGroup} from "@angular/forms";
import {combineLatest, Observable, of, Subject, Subscription, timer} from "rxjs";
import {User, UserService} from "@src/app/services/user.service";
import {catchError, debounceTime, map, startWith, switchMap, tap} from "rxjs/operators";

@Component({
  template: `
      <h1>Search example</h1>

      <form class="search-form" [formGroup]="searchForm" autocomplete="off">
          <div>
              <label for="firstName">First name</label>
              <input id="firstName" type="text" formControlName="firstName">
          </div>
          <div>
              <label for="lastName">Last name</label>
              <input id="lastName" type="text" formControlName="lastName">
          </div>
          <button type="button" (click)="refresh$.next()">Get fresh data</button>
      </form>

      <div>
          <h2>Search result</h2>
          <table [class.loading]="loading">
              <thead>
              <tr>
                  <th>First name</th>
                  <th>Last name</th>
              </tr>
              </thead>
              <tbody>
              <tr *ngFor="let user of users$ | async">
                  <td>
                      {{user.firstName}}
                  </td>
                  <td>
                      {{user.lastName }}
                  </td>
              </tr>
              </tbody>
          </table>
      </div>
  `,
})
export class ExampleComponent implements OnDestroy {
  searchForm = new FormGroup({
    firstName: new FormControl(),
    lastName: new FormControl(),
  });
  loading = false;

  refresh$ = new Subject();

  userInput$ = combineLatest([
    this.searchForm.valueChanges.pipe(debounceTime(200)),
    this.refresh$.pipe(
      startWith(null), // initiate data flow
    ),
  ]);

  private refreshSub: Subscription;
  userTotal = 0;

  users$: Observable<User[]> = this.userInput$.pipe(
    tap(_ => this.loading = true),
    switchMap(([params, _refresh]) => {
      return this.userService.search(params).pipe(
        map(({users, total}) => {
          this.userTotal = total;
          this.loading = false;
          return users;
        }),
        catchError((err) => {
          console.log('Oops, something went wrong!');
          return of([] as User[]);
        }),
      );
    }),
  )
  constructor(
    private userService: UserService,
  ) {
    this.refreshSub = timer(0, 60_000).subscribe(() => {
      this.refresh$.next();
    });
  }

  ngOnDestroy(): void {
    this.refreshSub.unsubscribe();
  }
}

```

All that to say that my prior exposure to “FRP” via Angular doesn’t really help me understand the “React” lib (nor the “Note” library for that matter)

Also worth mentioning “rxjs marbles” which are meant to help the programmer “visualize” the application of reactive functions (those functions are named “operators”), see here: [RxMarbles: Interactive diagrams of Rx Observables](https://rxmarbles.com/#filter)

Crazy to see that “old” flapjax ~~library~~ language! 🤯

---

<div class="post-metadata">

**Author:** ![bhoot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bhoot/32/5900_2.png) [@bhoot](https://discuss.ocaml.org/u/bhoot)\
**Post date:** [February 21, 2023, 7:55am UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/13 "2023-02-21T07:55:53Z")

</div>

The thing is Rx doesn’t do FRP. Its focuses more on events than on signals/behaviours.

From [ReactiveX - Intro](https://reactivex.io/intro.html) :

> ReactiveX may be functional, and it may be reactive, but “functional reactive programming” is a different animal. One main point of difference is that functional reactive programming operates on values that change _continuously_ over time, while ReactiveX operates on _discrete_ values that are emitted over time.

I think even this explanation is off, because FRP makes use of both signals/behaviours and events.

There is an analogy somewhere when I say that Elm similarly lost something from FRP when it moved to its MVU/Elm architecture.

Do take all of what I say with a grain of salt, simply because I’m still learning the ropes. Anyone more experienced is welcome to tear down my statements.

---

<div class="post-metadata">

**Author:** ![bhoot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bhoot/32/5900_2.png) [@bhoot](https://discuss.ocaml.org/u/bhoot)\
**Post date:** [February 21, 2023, 7:57am UTC](https://discuss.ocaml.org/t/jsoo-approach-to-react-gui/11382/14 "2023-02-21T07:57:28Z")

</div>

> [@dbuenzli](#):
>
> I don’t exactly know what these recent JavaScript libraries do, but after all these years I’m glad they are finally discovering [flapjax](https://www.flapjax-lang.org/) :–)

What was once learned, has been learned again.
