Sprinkle a bit of Reason into Create React App

Sep 30, 2017 · 3 min read

So you’ve decided to hop on the Reason hype train and you want to try it out in your app, the thing is you already have a big project using Create React App and don’t want to have to rewrite it from scratch or eject and have to manage everything yourself.

Enter reason-scripts, it’s the Reason equivalent of react-scripts and it’s easy enough to move from one to the other, the great thing is that your JavaScript code and Reason code are interoperable, so you can migrate your components one at a time, instead of doing a great big rewrite, awesome!

This isn’t intended as an introduction to Reason or to sell Reason to you, it’s intended to show you how you can start using it within an existing Create React App project.

If you’re looking for an introduction to Reason, I would recommend starting with the docs.

For Reason and React, I would start with:
A ReasonReact Tutorial by @jaredforsyth
A First Reason React app for Javascript developers by @urfriendjames

So let’s get started.

It is possible to create a new app using reason-scripts without having to go through this long-winded process, see their guide.

Install packages

This part is the easy part!

Start by moving from react-scripts to reason-scripts.

yarn remove react-scripts
yarn add reason-scripts

Then you need to install bs-platform.

yarn add --dev bs-platform

Install reason-reason.

yarn add --dev reason-react

Finally, install bs-jest

yarn add --dev bs-jest

Bucklescript config

./bsconfig.json

{
  "name": "reason-scripts",
  "sources": ["src"],
  "bs-dependencies": ["reason-react", "bs-jest"],
  "reason": {
    "react-jsx": 2
  },
  "bsc-flags": ["-bs-super-errors"],
  "refmt": 3
}

Migrate ./src/index.js to ./src/index.re

This part might take a bit more effort if you have added anything extra in your index.js, assuming you haven’t changed anything you can simply rename index.js to index.re and copy and paste the snippet below, (the index.re might have changed slightly in later versions, snippet is taken from v0.6.9 of reason-scripts)

[%bs.raw {|require('./index.css')|}];

[@bs.module "./registerServiceWorker"] external register_service_worker : unit => unit = "default";

ReactDOMRe.renderToElementWithId(<Appre />, "root");

register_service_worker();

If you have made some modifications the ReasonML guide and the reason-react guide on migrating from js to reason should be helpful.

Wrapping App.js

./src/Appre.re

[@bs.module "./App.js"] external reactClass : ReasonReact.reactClass = "default";

let make = (children) => ReasonReact.wrapJsForReason(~props=Js.Obj.empty(), ~reactClass, children);

Add files to .gitignore

.gitignore

# bucklescript
/lib
/types
.merlin

Done

If you run yarn start then everything should be working as before.

The completed source is on Github.