# ReasonReact: Reason bindings for React, and the ReScript question

> ReasonReact wraps React.js in Reason's type system and ships as an opam package with a PPX. It is a mature binding layer, but the README now points ReScript users elsewhere, and that split is the first thing to understand before adopting it.

**reasonml/reason-react** — Reason bindings for ReactJS

- Repository: https://github.com/reasonml/reason-react
- Website: https://reasonml.github.io/reason-react/
- Stars: 3,263 · Forks: 344
- Language: Reason
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/reasonml-reason-react

## What ReasonReact actually solves, and for whom

React is a JavaScript library. Writing it from Reason means every component you write crosses a language boundary, and without a binding layer that crossing is manual, untyped, and repeated in every file. ReasonReact is that binding layer. The README describes it plainly: ReasonReact is just React.js under the hood, and ReasonReact itself is an example of a binding. Nothing about the runtime is reimplemented. What you get is a typed surface over the same React you would otherwise call from JavaScript.

The audience is narrow and specific. It is for people who already build in Reason or OCaml, use opam and dune, and want React's component model inside that toolchain rather than beside it. The repository layout confirms this framing: reason-react.opam and reason-react-ppx.opam sit at the top level next to dune-project, and the build is driven by dune, not by a JavaScript bundler. If your project has no opam switch, there is nothing here for you to plug into.

The README also carries a warning at the top that changes the calculus. For ReScript users, it recommends @rescript/react instead, explaining that ReasonReact was previously designed for BuckleScript and was packaged into @rescript/react. That is not a deprecation of the Reason side. It is a fork in the road, and the two sides do not share a package.

## Components, the PPX, and where the type safety comes from

A ReasonReact component is a module with a make function. The README gives the canonical example, and the shape is worth reading carefully because it is the whole API in miniature:

```reason
/* Greeting.re */

[@react.component]
let make = (~name) => <h1> {React.string("Hello " ++ name)} </h1>
```

Two mechanisms are at work. The [@react.component] attribute is handled by the PPX, which is why the repository ships a separate reason-react-ppx.opam package and a ppx/ directory. The PPX rewrites that function into the component form React expects. The labelled argument ~name becomes the prop, and the JSX inside is Reason's JSX syntax, not a string template. React.string is the explicit conversion from a Reason string into a React node, which is how the binding keeps the two type systems honest instead of coercing silently.

The data flow is therefore: your Reason source, through the PPX at build time, into JavaScript that React executes. The build is dune's job. The Makefile shows the targets: make build runs dune build @all, make dev runs dune build -w @@default for watch mode, and make format runs ocamlformat through dune build @fmt --auto-promote. There is no separate transpiler configuration to maintain, because dune and the PPX are the pipeline.

One consequence of this design is that the PPX is not optional. If the PPX does not run, the JSX and the component attribute have no meaning. That is a build-system dependency, not a runtime one, but it is the kind of dependency that fails loudly at compile time rather than quietly at runtime.

## Installing ReasonReact and rendering a first component

The README does not inline installation steps. It points to the documentation site, specifically the installation page, which covers adding Reason to an existing React project such as Create React App or Next.js. What the repository does show is the toolchain the project itself uses, and that is the honest starting point.

The Makefile's install target is the project's own dependency setup: it installs opam dependencies with test and dev-setup flags, then runs npm install. The init target creates a local opam switch pinned to 5.2.0. Reproducing that flow in your own project looks like this:

```bash
opam switch create . 5.2.0 --no-install -y
opam install . --deps-only --with-test --with-dev-setup -y
```

The first command creates a local switch so the compiler version is pinned to the project rather than the machine. The second resolves the dependencies declared in the opam files. After that, make build runs dune build @all and you should see dune compile the libraries and the demo rather than a JavaScript bundler.

For a first real component, the Greeting.re example above is the smallest thing that exercises the whole path. Put it in a module, build with dune, and the PPX output is what React consumes. The demo/ directory in the repository contains index.html and main.re, which is the working reference for how a page is wired up. The README also points to reason-react-hacker-news as a full application if a single component is not enough context.

Integrating with an existing JavaScript project is explicitly supported. The README says ReasonReact is easy to integrate with Next.js, Create React App, JavaScript, Flowtype or TypeScript projects, and links that claim to the installation docs rather than spelling out the wiring. Treat that page as required reading; the repository alone does not document the bundler side.

## The ReScript split is the limitation that matters most

The most consequential thing about this repository is not a bug or a missing feature. It is the warning at the top of the README. ReScript users are told to use @rescript/react, and the explanation given is that ReasonReact was designed for BuckleScript before the rebranding, and got packaged into @rescript/react. The README links to a blog post on the ReScript site for more context.

Read that as a boundary rather than a defect. The Reason and ReScript ecosystems diverged, and the React binding went with each side. If you are starting a new project today and your team writes ReScript, ReasonReact is the wrong package, and no amount of familiarity with its API changes that. The reverse is also true: @rescript/react is not a drop-in for a Reason project on opam.

The second limitation is documentation depth. The README is short by design and delegates to the site. It gives one component example and a pointer to more examples. It does not document the PPX's full set of attributes, the props conventions beyond a labelled argument, or how hooks and effects are expressed. Those exist somewhere in the docs tree, but the repository README will not tell you. A team evaluating this from the README alone will underestimate how much of the learning curve lives on the website.

A third constraint is the toolchain. Building requires dune and opam, and the Makefile's targets assume opam exec prefixes the dune invocation. That is a real integration cost if the rest of your team lives in npm scripts. Nothing here is hard, but it is not free either.

## ReasonReact against writing React in TypeScript

The obvious alternative for a team that wants typed React is TypeScript, and the difference is not merely syntax. TypeScript annotates JavaScript. ReasonReact binds to React from a different language with its own compiler, its own package manager, and its own build tool. In TypeScript, the React types come from DefinitelyTyped packages and the compiler is tsc or your bundler's loader. In ReasonReact, the types come from the binding, the compiler is OCaml's, and the build is dune.

That changes what is easy. In TypeScript, adding an npm package is a single install and the ecosystem is the entire JavaScript world. In ReasonReact, using a JavaScript library means writing bindings, which the README describes as the mechanism for importing a popular project like lodash or your own local file. Bindings are a strength in the sense that they are explicit and typed, and a cost in the sense that someone has to write them.

The other real alternative is @rescript/react, and here the difference is smaller than it looks. Both bind React. The split is about which language and toolchain sits on top. If your codebase is Reason on opam, @rescript/react is not a substitute, and if it is ReScript, ReasonReact is not. Choosing between them is choosing your compiler, not your React binding.

The repository's own devDependencies pin react and react-dom at ^19.1.0, and the jest configuration points at compiled output under _build. That tells you the project tests against React 19. It does not tell you which React versions the published binding supports, since the README is silent on version compatibility.

## Maintenance, releases, and what the MIT licence means here

The repository is not archived, and the last push was on 2026-06-15. Releases are spaced roughly a year apart: 0.15.0 in August 2024, 0.16.0 in July 2025, and 0.17.0 in December 2025. That cadence is the honest signal. This is a binding layer that tracks React and the Reason toolchain, so it does not need weekly churn, but it is also not a project where you should expect rapid responses to edge cases.

The upgrade cost is tied to two moving parts. The first is React itself: the project's devDependencies track React 19, and a future major React release would be the kind of change that forces a binding update. The second is the compiler and PPX, which move with the Reason and OCaml ecosystem. Neither of those is under your control, and both can force a version bump on your side.

On licensing, the repository declares MIT in package.json and ships a LICENSE file at the top level. MIT is permissive and imposes no source-disclosure requirement on your application. That is a statement about the licence text, not legal advice; if your organisation has policies about dependency licences, route it through whoever handles that. The relevant fact for an engineering decision is simply that the licence is MIT, not a copyleft licence that would reach into your own code.

## Conclusion

Adopt ReasonReact if your project is already a Reason or OCaml codebase on opam and you want React's component model without leaving that toolchain. Do not adopt it if you write ReScript: the README recommends @rescript/react for that, and mixing the two ecosystems buys you nothing. Before committing, verify which React version your lockfile resolves, since the repository's own devDependencies track React 19, and confirm that the PPX builds under your opam switch, because the component syntax depends on it.

## FAQ

### Should I use ReasonReact or @rescript/react?

It depends on which language you write. The README recommends @rescript/react for ReScript users, noting that ReasonReact was previously designed for BuckleScript and got packaged into @rescript/react. ReasonReact remains the package for Reason projects built with opam and dune.

### How do I install ReasonReact?

The README does not inline installation steps and points to the documentation site's installation page instead. The repository's own setup, shown in the Makefile, creates a local opam switch and installs dependencies with opam before building with dune.

### Does ReasonReact need a PPX to compile components?

Yes. The [@react.component] attribute in the README's example is processed by the PPX, which is why the repository ships a separate reason-react-ppx.opam package and a ppx/ directory alongside the main library.

### Can ReasonReact be added to an existing JavaScript or TypeScript React project?

The README states that ReasonReact is just React.js under the hood and says it is easy to integrate with Next.js, Create React App, JavaScript, Flowtype or TypeScript projects. It links to the installation documentation for the actual steps rather than describing them in the README.

### Is ReasonReact actively maintained?

The repository is not archived, and the last push was on 2026-06-15. Releases have arrived roughly annually, with 0.15.0 in August 2024, 0.16.0 in July 2025 and 0.17.0 in December 2025.

## Sources

- [License: MIT](https://github.com/reasonml/reason-react/blob/main/LICENSE)
- [Project website](https://reasonml.github.io/reason-react/)
- [README](https://github.com/reasonml/reason-react/blob/main/README.md)
- [reasonml/reason-react on GitHub](https://github.com/reasonml/reason-react)
- [Releases](https://github.com/reasonml/reason-react/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/reasonml-reason-react
